【问题标题】:Create open instance delegate via reflection通过反射创建开放实例委托
【发布时间】:2026-01-28 15:05:01
【问题描述】:

为什么下面的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);

有机会让它工作吗?

【问题讨论】:

    标签: .net vb.net reflection delegates contravariance


    【解决方案1】:
    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
      

    我希望我不会太晚......

    【讨论】: