代表还是反思?

时间:2011-11-17 08:10:41

标签: c# reflection delegates

我有一个类,其中包含一个传递字符串的方法。该方法将对该字符串执行一些操作,然后将该字符串传递给某个对象,该对象可以使用该字符串执行其他操作。

所以它基本上是这样的:

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);
   }
}

现在这段代码运行良好,有反射的东西。但我想知道,这不应该是可能的(甚至更好吗?)与代表?如果是这样,我如何通过使用委托来实现这一点?

6 个答案:

答案 0 :(得分:5)

你不能使用接口:

 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
 }

答案 1 :(得分:4)

代表是一个更好的选择。

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();
    }
}

答案 2 :(得分:2)

您可以使用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);
    } 
} 

答案 3 :(得分:0)

比使用代表更好应该使用 Chain of Responsibility design pattern,它完全符合您的需要:)。

答案 4 :(得分:0)

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

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

但是,我会改为查看Action<string>(或者Func<string,string>),或者使用已知方法的接口。

答案 5 :(得分:0)

基本上,您希望更改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()); };
    }
}