2010-08-13 40 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