Christopher Leong
Christopher Leong

Reputation: 402

Cast object to generic delegate using system.type

I wish to cast an object into a generic delegate with system.type information so that I can invoke the delegate. The object is guaranteed to be convertible to the delegate.

Delegate example:

public delegate void CallbackFn<T>(InterfacedDataType<T> data) where T : InterfaceBase;

And the struct holding the callback object and type information:

public struct CallbackFnWrapper
{
    public System.Type T;
    public object delegateObject;

    public void Invoke(InterfaceBase data) 
    {
        ((CallbackFn<T>)(delegateObject)).Invoke((T)data); //Does not compile
    }
}

The line ((CallbackFn<T>)(delegateObject)).Invoke((T)data); does not compile for obvious reasons, however I fail to grasp the syntax required to do 2 things:

  1. Cast delegateObject to CallbackFn<T>
  2. Cast InterfaceBase data to InterfacedDataType<T>

Edit:

The invoke function has to be kept with the current signature:

public void Invoke(InterfaceBase data) 

This function is used in a scope where there is no type information available so I cant template that function.

Example Function where invoke is used:

List<CallbackFnWraper> fnlist;
foreach(var fn in fnlist) fn.Invoke(somedata);

Edit 2:

I made a small program that is "Minimal, Complete, and Verifiable" so if anyone wants to give it a shot:

public class DataTypeBase { }

public class DataTypeDerivedA : DataTypeBase
{
    public int i = 0;
}

public class DataTypeDerivedB : DataTypeBase
{
    public char c = ' ';
}

public class RunEnvironment
{
    public void Run()
    {
        DataTypeDerivedA a = new DataTypeDerivedA();
        a.i = 555;
        DataTypeDerivedB b = new DataTypeDerivedB();
        b.c = '@';
        Wrapper w1 = MakeWrapper<DataTypeDerivedA>(Test1);
        Wrapper w2 = MakeWrapper<DataTypeDerivedB>(Test2);

        w1.Invoke(a);
        w2.Invoke(b);
    }

    public Wrapper MakeWrapper<T>(CallbackFn<T> fn) where T : DataTypeBase
    {
        Wrapper w = new Wrapper();
        w.T = typeof(T);
        w.delegateObject = fn;
        return w;
    }

    public void Test1(DataTypeDerivedA data)
    {
        System.Console.WriteLine(data.i);
    }

    public void Test2(DataTypeDerivedB data)
    {
        System.Console.WriteLine(data.c);
    }
}

public delegate void CallbackFn<T>(T data) where T : DataTypeBase;
public struct Wrapper
{
    public System.Type T;
    public object delegateObject;

    public void Invoke(DataTypeBase data)
    { 
        ((CallbackFn<T>)(delegateObject)).Invoke((T)(data)); //Won't compile
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        RunEnvironment r = new RunEnvironment();
        r.Run();
    }
}

Upvotes: 1

Views: 1389

Answers (1)

Jamiec
Jamiec

Reputation: 136074

Actually this turned out to be pretty simple. You simply needed to cast your delegateObject to a Delegate type and call DynamicInvoke.

public struct Wrapper
{
    public System.Type T;
    public object delegateObject;

    public void Invoke(DataTypeBase data)
    { 
       ((Delegate)delegateObject).DynamicInvoke(data); //Will compile
    }
}

Working example: http://rextester.com/CQG34502

Upvotes: 3

Related Questions