通过反射创建委托
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<Foo.Bar>
。但是,要使用它,您需要继续使用反射,因此您需要找到符合签名void(Foo.Bar)
的MethodInfo
,并调用Delegate.CreateDelegate
来创建委托。你需要Delegate.DynamicInvoke
来执行它。
Delegate call = Delegate.CreateDelegate(actionType, ...);
...
call.DynamicInvoke(someBar);
有些事情告诉我这不是你想的......
【讨论】:
我会在Delegate.CreateDelegate(actionType, ...);
中的...
中添加什么?我认为您的解决方案是我所需要的,因为无论如何我都会将此委托传递给源程序集中的构造函数。【参考方案2】:
您不能在调用代码中调用它Action<Foo.Bar>
,因为如果您在编译时不引用它,您将无法访问该类型定义。由于委托是逆变的,您可以返回 Action<Object>
并使用它,或者使用 Action<IBar>
,其中 IBar
接口在引用的程序集中定义,并由 Foo.Bar
实现。
如果您确实返回了Action<Object>
,则必须通过反射使用Foo.Bar
成员(如果使用C# 4.0,则使用dynamic
)或将其强制转换为Foo.Bar
,其中强制转换代码有参考到定义Foo.Bar
的程序集。
【讨论】:
“你不能在你的调用代码中调用它 Action以上是关于通过反射创建委托的主要内容,如果未能解决你的问题,请参考以下文章
反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性字段),而不去使用Invoke方法)