2011-10-05 7 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); 
     } 
    } 


}