动态地代理集合接口

时间:2011-10-05 07:29:23

标签: c# proxy adapter dynamicobject

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

IList<T>的代理是否可能?

e.g。

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

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

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

1 个答案:

答案 0 :(得分: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);
        }
    }


}