2011-10-05 58 views
2

我偶尔有原因来编写集合类适配器,即为实现代理其方法的IList<T>类创建适配器,并添加一些额外的功能。 IList接口有许多方法/属性,我想知道直通式代理方法是否可以动态实现?我看了一下DynamicObject,但只能找到几个代理DTO类的简单例子,即代理一个只有属性的类。动态地代理集合接口

是否可以代理IList<T>

例如

public class ListProxy : IList<T> 
{ 
    private IList<T> _adaptee; 

    public ListProxy(IList<T> adaptee) 
    { 
    _adaptee = adaptee 
    } 

    // dynamically implement straight-through IList methods/properties 
} 

回答

2

是这样的吗?

using System; 
using System.Collections.Generic; 
using System.Reflection; 
using System.Runtime.Remoting.Messaging; 
using System.Runtime.Remoting.Proxies; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     IList<string> listProxy = MyProxyGenerator.Create<IList<string>>(new ListProxy<string>(new List<string>() { "aa","bb" })); 
     bool b1 = listProxy.Contains("aa"); 
     bool b2 = listProxy.Contains("cc"); 
     int count = listProxy.Count; 
     string s = listProxy[1]; 
    } 

    public class ListProxy<T> 
    { 
     private IList<T> _adaptee; 

     //Only method needed by proxy generator 
     object Adaptee 
     { 
      get { return _adaptee; } 
     } 

     public ListProxy(IList<T> adaptee) 
     { 
      _adaptee = adaptee; 
     } 
    } 

    class MyProxyGenerator : RealProxy 
    { 
     Type _Type; 
     object _Instance; 

     public static T Create<T>(object instance) 
     { 
      return (T)new MyProxyGenerator(typeof(T),instance).GetTransparentProxy(); 
     } 

     MyProxyGenerator(Type type,object instance) : base(type) 
     { 
      _Type = type; 
      _Instance = instance.GetType().InvokeMember("get_Adaptee", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, instance, null); 
     } 

     public override IMessage Invoke(IMessage msg) 
     { 
      IMethodCallMessage methodMessage = new MethodCallMessageWrapper((IMethodCallMessage)msg); 
      string method = (string)msg.Properties["__MethodName"]; 
      object[] args = (object[])msg.Properties["__Args"]; 

      object retObj = _Instance.GetType().InvokeMember(method, BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,null,_Instance,args); 
      return new ReturnMessage(retObj,methodMessage.Args,methodMessage.ArgCount,methodMessage.LogicalCallContext,methodMessage); 
     } 
    } 


}