通过反射创建委托

Posted

技术标签:

【中文标题】通过反射创建委托【英文标题】:Create delegate via reflection 【发布时间】:2011-03-02 17:48:18 【问题描述】:

给定一个包含

的程序集
namespace Foopublic class Bar;

如何在编译时不引用第一个程序集的情况下从另一个程序集创建Action<Foo.Bar>

【问题讨论】:

“不引用第一个程序集”是什么意思?如果您想使用该程序集中的类型,则需要以某种方式引用它。 对不起,我的意思是没有将其添加为对 Visual Studio 项目的引用。即使用 Assembly.LoadFrom() 来加载它,这样就没有编译时依赖。 @LukeH - 编辑问题更清晰。感谢您的意见。 如果由于在编译时没有类型而无法将委托分配给变量,您会怎么处理?你想达到什么目的? @dtb - 在我的场景中,我在源程序集中有一个接受Action<Foo.Bar> 的构造函数。所以我希望创建一个Action<Foo.Bar> 通过反射传递给所述构造函数。 【参考方案1】:

如果你使用

Type barType = Type.GetType("Foo.Bar, whateverassembly");
Type actionType = typeof(Action<>).MakeGenericType(barType);

actionType 现在将代表Action&lt;Foo.Bar&gt;。但是,要使用它,您需要继续使用反射,因此您需要找到符合签名void(Foo.Bar)MethodInfo,并调用Delegate.CreateDelegate 来创建委托。你需要Delegate.DynamicInvoke 来执行它。

Delegate call = Delegate.CreateDelegate(actionType, ...);
...
call.DynamicInvoke(someBar);

有些事情告诉我这不是你想的......

【讨论】:

我会在Delegate.CreateDelegate(actionType, ...); 中的... 中添加什么?我认为您的解决方案是我所需要的,因为无论如何我都会将此委托传递给源程序集中的构造函数。【参考方案2】:

您不能在调用代码中调用它Action&lt;Foo.Bar&gt;,因为如果您在编译时不引用它,您将无法访问该类型定义。由于委托是逆变的,您可以返回 Action&lt;Object&gt; 并使用它,或者使用 Action&lt;IBar&gt;,其中 IBar 接口在引用的程序集中定义,并由 Foo.Bar 实现。

如果您确实返回了Action&lt;Object&gt;,则必须通过反射使用Foo.Bar 成员(如果使用C# 4.0,则使用dynamic)或将其强制转换为Foo.Bar,其中强制转换代码有参考到定义Foo.Bar 的程序集。

【讨论】:

“你不能在你的调用代码中调用它 Action”——是的,我意识到了这一点。回复:逆变 - 抱歉,我没有指定 .NET 3.5。我会修复标签。

以上是关于通过反射创建委托的主要内容,如果未能解决你的问题,请参考以下文章

反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性字段),而不去使用Invoke方法)

什么是反射技术?什么是静态代理?什么是动态代理?什么是aop

Reflection(反射)

反射方法创建委托

反射资料整理

C#怎么使用反射获取事件的响应方法