委托或反射

本文关键字:反射 | 更新日期: 2023-09-27 18:14:49

我有一个类,其中一个方法将传递一个字符串。这个方法会对这个字符串做一些事情然后它把这个字符串传递给一个特定的对象这个对象可以对这个字符串做其他的事情

所以它基本上是这样的:

class Main
{
     public Main()
     {
         strClass str = new strClass(this);
     }
     public function handler ( )
     {
         console.log("No string is passed yet, but this method is called from receiveData()");
     }
}
class strClass
{
    object handler;
    public strClass ( handler )
    {
        // save the object
        this.handler = handler;
    }
    public receiveData ( string str )
    {
        // This method does some stuff with the string
        // And it then passes it on to the supplied object (handler) which will do
        // the rest of the processing
        // I'm calling the "handler" method in the object which got passed in the 
        // constructor
        Type thisType = this.handler.GetType();
        MethodInfo theMethod = thisType.GetMethod("handler");
        theMethod.Invoke(this.handler, null);
   }
}
现在这段代码工作得很好,有了反射的东西。但我想知道,这难道不可能(甚至更好?)与代表??如果是这样,我如何通过使用委托来实现这个?

委托或反射

你就不能用接口来代替吗:

 interface IStringHandler {
     void HandleString(string s);
 }

 class strClass 
 {
      IStringHandler handler = null;
      public strClass(IStringHandler handler)
      {
          this.handler = handler;
      }
      public void ReceiveData(string s)
      {
          handler.HandleString(s);
      }
 }

 class Main : IStringHandler
 {
      // Your code
 }

委托是一个更好的选择。

class Main
{
     public Main()
     {
         StrClass str = new StrClass(this.Handler);
     }
     public void Handler ( )
     {
         //called from recieve data
     }
}
class StrClass
{
    readonly Action _handler;
    public StrClass ( Action callback)
    {
        // save the object
        this._handler = callback;
    }
    public void receiveData( string str )
    {
        this._handler();
    }
}

您可以像这样使用Action:

class Main 
{
    public Main()      
    {
        strClass str = new strClass(newString => 
        {
             console.log("This string I got back: " + newString);      
        });
    } 
 }  
 class strClass 
 {     
    Action<string> callback;
    public strClass (Action<string> callback) 
    { 
        // save the action
        this.callback = callback;     
    }
    public receiveData ( string str )     
    {
        // Do something with the string
        callback(str);
    } 
} 

比使用委托更好的方法是使用责任链设计模式,它正好满足您的需求:)

首先,如果必须按名称调用未知方法,请使用dynamic -它为此进行了大量优化(尽管仍然不是一个好主意):

((dynamic)handler).handler(); // but please don't use this! see below

然而,我宁愿看看Action<string>(或Func<string,string>),或一个已知方法的接口。

基本上,您希望更改StrClass对象对开始接收的数据的反应方式。

类似这样,在Main和通用HandlerObject中都有处理方法:

class StrClass : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = null;
    public void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, e);
    }
    private string receivedString;
    public string ReceivedString
    {
        get;
        set
        {
            string oldStr = receivedString;
            receivedString = value;
            PropertyChanged(receivedString, new PropertyChangedEventArgs("ReceivedString"));
        }
    }
    public void receiveData(string str)
    {
        //event fires here
        ReceivedString = str;
    }
}
class HandlerObject
{
    public void HandlerMethod1(string s)
    {
        //magic
    }
    public void HandlerMethod2(string s)
    {
        //different kind of magic
    }
}
class Program
{
    static void HandlerMethod3(string s)
    {
        //another kind of magic!
    }
    static void Main(string[] args)
    {
        StrClass class1 = new StrClass();
        StrClass class2 = new StrClass();
        StrClass class3 = new StrClass();
        HandlerObject handler = new HandlerObject();
        class1.PropertyChanged += (s, e) => { handler.HandlerMethod1(s.ToString()); };
        class2.PropertyChanged += (s, e) => { handler.HandlerMethod2(s.ToString()); };
        class3.PropertyChanged += (s, e) => { HandlerMethod3(s.ToString()); };
    }
}