سؤال

I have occasionally had cause to write collection class adapters, i.e. create an adapter for a class that implements IList<T> proxying its methods, whist adding some extra functionality. The IList interface has numerous methods / properties, I was wondering whether the straight-through proxy methods could be implemented dynamically? I had a look at DynamicObject, but could only find a few simple examples that proxy DTO classes, i.e. proxying a class that just has properties.

Is the proxying of IList<T> possible?

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
}
هل كانت مفيدة؟

المحلول

Something like this?

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);
        }
    }


}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top