通过反射创建打开的实例委托

时间:2014-02-07 10:58:03

标签: .net vb.net reflection delegates contravariance

为什么以下Delegate.CreateDelegate会产生运行时ArgumentException?

static class Module1
{
    public static void Main()
    {
        MyDataObject mdo = new MyDataObject();
        mdo.DoMagic("Hello");
    }

    #region Assembly A
    public class BusinessObject
    {
    }

    public class MyBusinessObject : BusinessObject
    {

        public void DoMagic(string s)
        {
            Console.WriteLine(s);
        }
    }
    #endregion

    #region Assembly B
    public class MyDataObject
    {
        private delegate void DoMagicDel(BusinessObject bo, string s);

        private DoMagicDel delDoMagic;
        public void DoMagic(string s)
        {
            BusinessObject bo = (BusinessObject)Activator.CreateInstance(Type.GetType("Module1+MyBusinessObject"));
            MethodInfo mi = bo.GetType().GetMethod("DoMagic", BindingFlags.Public | BindingFlags.Instance);
            // ArgumentException: Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
            delDoMagic = (DoMagicDel)Delegate.CreateDelegate(typeof(DoMagicDel), null, mi);
            delDoMagic(bo, s);
        }
    }
    #endregion
}

如果程序集A具有对程序集B的项目引用,反之则不然。 当我将第一个参数DoMagicMel更改为MyBusinessObject类型时,它可以工作。但是因为程序集B不知道这种类型的程序集A,所以这只适用于我的简化示例:

private delegate void DoMagicDel(MyBusinessObject bo, string s);

有机会让这个工作吗?

1 个答案:

答案 0 :(得分:2)

ArgumentException: Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.

为什么以下Delegate.CreateDelegate会生成运行时ArgumentException

  • 因为DoMagicDel的签名与mi描述的方法的签名不符。

有机会让这个工作吗?

  • 是的,使用MakeGenericType来匹配mi的签名:

    #region Assembly B
    public class MyDataObject
    {
        public delegate void DoMagicDel<T1>(T1 arg1, string arg2);
        private static Delegate delDoMagic;
        public void DoMagic(string s)
        {
            var bo = Activator.CreateInstance("Module1", "Module1.MyBusinessObject").Unwrap();
            MethodInfo mi = bo.GetType().GetMethod("DoMagic", BindingFlags.Public | BindingFlags.Instance);
            var doMagicDelType = typeof(DoMagicDel<>).MakeGenericType(bo.GetType());            
            if (delDoMagic == null)
                delDoMagic = Delegate.CreateDelegate(doMagicDelType, null, mi);
            delDoMagic.DynamicInvoke(bo, s);
        }
    }
    #endregion
    

我希望我不会太迟......