总而言之,我会同意他人的意见。我使用了Castle的DynamicProxy,我认为它很棒。你可以用它做一些非常惊人和强大的东西。也就是说,如果你还在考虑编写自己的代码,请继续阅读:
如果你对发布IL不感兴趣,可以使用一些使用Lambda表达式的新技术来生成代码。但是,这不是一项简单的任务。
这里有一个如何我使用Lambda表达式生成任何.NET事件动态事件处理的例子。您可以使用类似的技术来生成动态接口实现。
public delegate void CustomEventHandler(object sender, EventArgs e, string eventName);
Delegate CreateEventHandler(EventInfo evt, CustomEventHandler d)
{
var handlerType = evt.EventHandlerType;
var eventParams = handlerType.GetMethod("Invoke").GetParameters();
//lambda: (object x0, EventArgs x1) => d(x0, x1)
// This defines the incoming parameters of our dynamic method.
// The method signature will look something like this:
// void dynamicMethod(object x0, EventArgs<T> x1)
// Each parameter is dynamically determined via the
// EventInfo that was passed.
var parameters = eventParams.Select((p, i) => Expression.Parameter(p.ParameterType, "x" + i)).ToArray();
// Get the MethodInfo for the method we'll be invoking *within* our
// dynamic method. Since we already know the signature of this method,
// we supply the types directly.
MethodInfo targetMethod = d.GetType().GetMethod(
"Invoke",
new Type[] { typeof(object), typeof(EventArgs), typeof(string) }
);
// Next, we need to convert the incoming parameters to the types
// that are expected in our target method. The second parameter,
// in particular, needs to be downcast to an EventArgs object
// in order for the call to succeed.
var p1 = Expression.Convert(parameters[0], typeof(object));
var p2 = Expression.Convert(parameters[1], typeof(EventArgs));
var p3 = Expression.Constant(evt.Name);
// Generate an expression that represents our method call.
// This generates an expression that looks something like:
// d.Invoke(x0, x1, "eventName");
var body = Expression.Call(
Expression.Constant(d),
targetMethod,
p1,
p2,
p3
);
// Convert the entire expression into our shiny new, dynamic method.
var lambda = Expression.Lambda(body, parameters.ToArray());
// Convert our method into a Delegate, so we can use it for event handlers.
return Delegate.CreateDelegate(handlerType, lambda.Compile(), "Invoke", false);
}
问候,
-Doug
动态代理框架必须是完成这一任务的最简单的方法。否则,我会建议编译您的示例实现并通过.NET Reflector或ILDASM检查生成的IL。这应该让你知道需要发射什么。 – 2010-08-13 15:31:23
我100%同意丹尼尔。你使用过Castle的DynamicProxy?您可以通过几行代码获取某些内容。那真的太复杂了吗? (为什么讨厌外部依赖?有时候,最好的工具已经被写入并且是免费的,为什么不使用它?) – 2010-08-13 15:59:43
在这种情况下,Castle DynamicProxy是我的首选工具。维护Reflection.Emit代码不好玩。 虽然我尊重您对依赖关系的关注,但这是Mike Barnett给我们的ILMerge(例如RhinoMocks使用DynamicProxy,但将它合并到它们的程序集中以提高可重用性)。 – FuleSnabel 2010-08-13 16:58:03