w00
w00

Reputation: 26812

delegate or reflection?

I have a class with a method in which a string will be passed. That method will do some things to that string and it then passes the string to a certain object which can do other things with the string.

So it basically looks like this:

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

Now this code works good, with the reflection stuff. But i was wondering, shouldn't this be possible (and maybe even better?) with delegates?? If so, how can i implement this by using a delegate instead?

Upvotes: 1

Views: 265

Answers (6)

Alex
Alex

Reputation: 23310

Basically, you want to change how your StrClass object react to data begin received. Sounds like events to me.

something like this, where you have handling methods both in the Main and in a generic 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()); };
    }
}

Upvotes: 0

Fischermaen
Fischermaen

Reputation: 12468

You can do it with an Action like this:

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

Upvotes: 2

Darren Lewis
Darren Lewis

Reputation: 8498

A delegate is a better option here.

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

Upvotes: 4

Marc Gravell
Marc Gravell

Reputation: 1064134

Firstly, if you must call an unknown method by name, use dynamic - it is heavily optimised for this (although still not a great idea):

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

However, I would instead look at either an Action<string> (or maybe Func<string,string>), or an interface with a known method on it.

Upvotes: 0

richn
richn

Reputation: 164

Even nicer than using delegates whould be using the Chain of Responsibility design pattern, which does exactly what you need :).

Upvotes: 0

faester
faester

Reputation: 15086

Couldn't you use interfaces instead:

 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
 }

Upvotes: 5

Related Questions