2010-08-13 47 views
2

比方说,我有以下接口:使用Reflection.Emit的实现接口

public interface IMyService 
{ 
    void SimpleMethod(int id); 
    int Hello(string temp); 

} 

而且要产生一类,看起来像这样(使用反射发出)。

public class MyServiceProxy : IMyService 
{ 
    IChannel _channel; 

    public MyServiceProxy(IChannel channel) 
    { 
    _channel = channel; 
    } 

    public void SimpleMethod(int id) 
    { 
    _channel.Send(GetType(), "SimpleMethod", new object[]{id}); 
    } 

    public int Hello(string temp) 
    { 
    return (int)_channel.Request(temp); 
    } 
} 

我该怎么做?我检查过各种动态代理和模拟框架。他们有点复杂,不容易遵循(我不想要外部依赖)。为接口生成代理应该不那么困难。任何人都可以告诉我如何?

+0

动态代理框架必须是完成这一任务的最简单的方法。否则,我会建议编译您的示例实现并通过.NET Reflector或ILDASM检查生成的IL。这应该让你知道需要发射什么。 – 2010-08-13 15:31:23

+0

我100%同意丹尼尔。你使用过Castle的DynamicProxy?您可以通过几行代码获取某些内容。那真的太复杂了吗? (为什么讨厌外部依赖?有时候,最好的工具已经被写入并且是免费的,为什么不使用它?) – 2010-08-13 15:59:43

+1

在这种情况下,Castle DynamicProxy是我的首选工具。维护Reflection.Emit代码不好玩。 虽然我尊重您对依赖关系的关注,但这是Mike Barnett给我们的ILMerge(例如RhinoMocks使用DynamicProxy,但将它合并到它们的程序集中以提高可重用性)。 – FuleSnabel 2010-08-13 16:58:03

回答

1

总而言之,我会同意他人的意见。我使用了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