Activator.CreateInstance 与 Delegate 参数

Posted

技术标签:

【中文标题】Activator.CreateInstance 与 Delegate 参数【英文标题】:Activator.CreateInstance with Delegate parameter 【发布时间】: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 我更新了我的问题以包含更多详细信息和解决方案。 【参考方案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);

【讨论】:

以上是关于Activator.CreateInstance 与 Delegate 参数的主要内容,如果未能解决你的问题,请参考以下文章

笔记 Activator.CreateInstance(Type)

Activator.CreateInstance(type) 抛出异常

Activator.CreateInstance - 如何创建具有参数化构造函数的类的实例

ProtoBuf-net AsReference 需要 Activator.CreateInstance 中的公共构造函数?

使用 Activator.CreateInstance() 创建的对象不会等待整个对象在 Release 上初始化

C# Activator.CreateInstance 动态创建类的实例