делегат или рефлексия? - PullRequest
       3

делегат или рефлексия?

1 голос
/ 17 ноября 2011

У меня есть класс с методом, в котором будет передана строка. Этот метод будет выполнять некоторые действия с этой строкой, а затем передает строку определенному объекту, который может выполнять другие действия со строкой.

Так что в основном это выглядит так:

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 ]

5 голосов
/ 17 ноября 2011

Не могли бы вы вместо этого использовать интерфейсы:

 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
 }
4 голосов
/ 17 ноября 2011

Делегат - лучший вариант здесь.

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 голосов
/ 17 ноября 2011

Вы можете сделать это с 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);
    } 
} 
0 голосов
/ 17 ноября 2011

По сути, вы хотите изменить то, как ваш 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()); };
    }
}
0 голосов
/ 17 ноября 2011

Во-первых, если вы должны вызвать неизвестный метод по имени, используйте dynamic - он сильно оптимизирован для этого (хотя все еще не очень хорошая идея):

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

Однако вместо этого я бы посмотрел либо на Action<string> (или, может быть, Func<string,string>), либо на интерфейс с известным методом.

0 голосов
/ 17 ноября 2011

Даже лучше, чем использовать делегатов, которые используют шаблон проектирования Цепочка ответственности , который делает именно то, что вам нужно:).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...