Search code examples
c#objecttypes

How to pass a method parameter as object and convert it back to it's type?


I would like to pass any type variable to a method and in the method convert it back to it's original type. I am looking to wrap DevExpress Messenger functionality and the message that is sent needs to be the type it is registered with. I always thought this was not possible, so I am baffled as to how this send is received in the DevExpress sample code below when any type object can be passed to the Send method:

public class MyMessage {}
public class Recipient {
    public Recipient() {
        // Receives messages of the `string` type.
        Messenger.Default.Register<string>(this, OnMessage1);
        // Receives messages of a custom `MyMessage` type.
        Messenger.Default.Register<MyMessage>(this, OnMessage2);
    }
    void SendMessages() {
        // Sends messages of the `string` type.
        Messenger.Default.Send("test");
        // Sends messages of a custom `MyMessage` type.
        Messenger.Default.Send(new MyMessage());
    }
    void OnMessage1(string message) {
        //...
    }
    void OnMessage2(MyMessage message) {
        //...
    }
}

I know I can do this with generics but I don't want to change the method signature. With the same signature I can just find/replace Message.Default.Send with MessengerWrapper.Send. If I have to use generics I have to find the types for at least 400 calls.

public static void Send<T>(object message)
        {
            Messenger.Default.Send(message: (T)message);
            SIMSGlobal.LogInformationMessageSend(token);
        }

Solution

  • If you use T as your parameter type public static void Send<T>(T message) then the compiler is smart enough to infer the type from the function parameter and you can still call it like so: MessengerWrapper.Send(message); rather than explicitly passing the type MessengerWrapper.Send<MyMessage>(message);

    So you will still be able to do your bulk find/replace without any issues.

    This has the added benefit of not requiring any casting to T inside the function call itself.

    public static void Send<T>(T message) {
        Messenger.Default.Send(message);
        SIMSGlobal.LogInformationMessageSend(token);
    }
    

    Other than that you could use reflection to debox the object back into its original type, but this method is pretty ugly and comes with a lot of gotchas.