使用system.type

时间:2017-07-20 08:19:01

标签: c# generics delegates

我希望将一个对象转换为带有system.type信息的泛型委托,以便我可以调用该委托。保证对象可以转换为委托。

委托示例:

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

包含回调对象和类型信息的结构:

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

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

由于显而易见的原因,行((CallbackFn<T>)(delegateObject)).Invoke((T)data);无法编译,但是我无法掌握执行两项操作所需的语法:

  1. delegateObject投放到CallbackFn<T>
  2. InterfaceBase data投放到InterfacedDataType<T>
  3. 修改

    调用函数必须与当前签名保持一致:

    public void Invoke(InterfaceBase data) 
    

    此功能用于没有可用类型信息的范围,因此我无法模板化该功能。

    示例使用invoke的函数:

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

    编辑2:

    我制作了一个小程序,即“最小,完整,可验证的”#34;所以如果有人想试一试:

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

1 个答案:

答案 0 :(得分:2)

实际上事实证明这很简单。您只需将delegateObject转换为Delegate类型并致电DynamicInvoke

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

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

工作示例:http://rextester.com/CQG34502