Home > Software design >  C# - How to get the value of a passed lambda expression
C# - How to get the value of a passed lambda expression

Time:09-16

I have a special case. I need to rewrite a library and I do not have the original code. To make the discussion clearer lets call the library HandlerLibOld and HandlerLibNew.

I want to make HandlerLibNew that shall replace HandlerLibOld.

I have an application that uses this library, and it is big application with 1000s of calls to the library. I rather not have to change the application code.

Sample application code

public class MyMessage : MyBaseClass
{
   public int ValueA {get;set;}
   public int ValueB {get;set;}
}
public class MyOtherMessage : MyBaseClass
{
   public int ValueC {get;set;}
   public int ValueD {get;set;}
}

public class Sender
{
   Handler handler = new Handler();
   handler.Send<MyMessage>(m => { m.ValueA=10; m.ValueB=20; });
}

Notice the line handler.Send<MyMessage>(m => { m.ValueA=10; m.ValueB=20; });. It uses a lambda expression to define an object of the MyMessage and sets two properties of this object. Notice that I rather not have to change this code.

Maybe I have misunderstood what the lambda expression does, but the point is I need to tell the Handler.Send about the values ValueA and ValueB.

Now I want to write the implementation of the Send method of the Handler. The tricky part is that the lambda expression makes it an action, but I want to get the MyMessage object instance. How can I achieve that? Do I need to use reflection somehow?

My attempts

I have tried:

public class Handler
{
    public void Send<T>(Action<T> actionmessage)
    {
        // actionmessage is an object of type Action<T>, 
        // I want to get the object of type T that was passed into the method.
    }
}

I have also tried:

public class Handler
{
    public void Send<T>(T message)
    {
         // This will not compile. I get:
         //    Cannot convert lambda expression 
         //    to type 'object' because it is not a delegate type
    }
}

I know it is possible somehow because this works with the HandlerLibOld. How can I achieve the same with HandlerLibNew? I don't have access to the code of HandlerLibOld.

CodePudding user response:

In order for that Action to work, you must have an instance of T to begin with:

public void Send<T>(Action<T> actionMessage)
        where T: new()
    {
        var input = new T();
        actionMessage(input);
        //T has now valueA and valueB populated
        //do more with input T
        //send
    }

Now if T were to have a constraint such as implementing a certain interface, you can do more stuff on the object itself. If you are using base classes you must be careful with object slicing.

  • Related