【问题标题】:Activator.CreateInstance with Delegate parameterActivator.CreateInstance 与 Delegate 参数
【发布时间】:2021-09-18 18:58:11
【问题描述】:

我想通过反射从第三方程序集创建一个内部类的实例。

类看起来像这样

    internal sealed class SomeClass
    {
        public delegate object SomeDelegate(object value);

        public SomeDelegateHandler { get; private set; }

        public SomeClass(SomeDelegate handler)
        {
            this.Handler = handler;
        }
    }

通常我会使用反射来创建内部类的实例,但我需要传递一个SomeDelegate 委托。

由于该委托在内部类中,我也需要通过反射创建该委托的实例。但是我已经尝试过的所有方法都不起作用

这是我迄今为止尝试过的。

// This is the method that I need to pass as an argument
public static object SomeDelegateImplementation(object value)
{
    return value;
}

public void Main()
{
    // example: create SomeClass without reflection 
    // (this is how SomeClass is usually constructed);
    var instance = new SomeClass(SomeDelegateImplementation);

    // setup: get the ConstructorInfo so I can use 
    // ctor.Invoke(...) to create an instance of that class
    var assembly = typeof(ThirdParty.OtherClass).Assembly;
    var type = assembly.GetType("ThirdParty.SomeClass", true, true);
    var ctor = type.GetConstructors()[0];

    // method one (doesn't work)
    // compiler error: cannot convert method group 'SomeDelegateImplementation' to non-delegate type 'object'. Did you intend to invoke the method?
    var args = new object[]{ SomeDelegateImplementation }; 
    var instance = ctor.Invoke(args);

    // method two (doen't work)
    // throws a runtime error during invoke: 
    // error converting object with type "System.Func`2[System.Object,System.Object]" to type "ThirdParty.SomeClass+SomeDelegate".
    Func<object, object> someDelegateImplementation = SomeDelegateImplementation;
    var args = new object[]{ (Delegate)someDelegateImplementation }; 
    var instance = ctor.Invoke(args);
}

【问题讨论】:

  • 您知道要在编译时创建的委托类型,还是动态的?目前尚不清楚您的真实背景是什么。但 Delegate.CreateDelegate 可能是你想要的,如果它都是动态的。
  • 我同意乔恩的观点。委托总是引用一个方法(包括匿名方法和 lambdas)。因此,为了创建委托,您需要将引用的方法与您要创建的新委托变量连接起来。在反射MethodInfo.CreateDelegateDelegate.CreateDelegate 是要走的路。
  • @JonSkeet 我知道类型,但它在第三方程序集的内部类中,所以我也需要重新选择。 var t = assembly.GetType("ThirdParty.SomeClass+SomeDelegateHandler ", true, true); var method = this.GetType().GetMethod("SomeDelegateImplementation"); var args = new [] { Delegate.CreateDelegate(t, m); } 有效。谢谢乔恩,不知道CreateDelegate。如果您将此作为答案发布,我可以将其标记为已接受。
  • 如果你编辑问题来澄清它,我会这样做,最好是一个完整的例子。这将使它成为对未来访问者更有用的问题。
  • @JonSkeet 我更新了我的问题以包含更多详细信息和解决方案。

标签: c# .net reflection delegates


【解决方案1】:

解决方案

感谢@JonSkeet,我设法使用Delegate.CreateDelegate 创建了SomeClass 的实例

    Assembly assembly = typeof(ThirdParty.OtherClass).Assembly;
    Type type = assembly.GetType("ThirdParty.SomeClass", true, true);
    ConstructorInfo ctor = type.GetConstructors()[0];

    // get a reference to the original delegate type
    Type someDelegateHandler Type =
        assembly.GetType("ThirdParty.SomeClass+SomeDelegateHandler", true, true);

    // get a reference to my method
    MethodInfo someDelegateImplementationMethod = 
        typeof(Program).GetMethod("SomeDelegateImplementation", 
            BindingFlags.Static | BindingFlags.NonPublic);

    // create a delegate that points to my method
    Delegate someDelegateImplementationDelegate = 
        Delegate.CreateDelegate(
            someDelegateHandler, someDelegateImplementationMethod);

    object[] args = new object[]{ someDelegateImplementationDelegate  };
    object instance = ctor.Invoke(args);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多