Castle DynamicProxy: Get unproxied object

前端 未结 4 999
旧时难觅i
旧时难觅i 2020-12-06 18:44

I\'m using Castle DynamicProxy to add an interceptor to my types. Now I need to get the underlying base type (NOT the proxy itself).

I found a few hints on SO that s

相关标签:
4条回答
  • 2020-12-06 19:19

    If you are building an inheritance-based proxy (generator.CreateClassProxy<MyClass>()) the proxy is the target.

    0 讨论(0)
  • 2020-12-06 19:24

    If you don't have an invocation object available, or if you observe 'Castle.Proxies.IXeroServiceProxy.__target' is inaccessible due to its protection level when trying @s1mm0t's answer, you can try the following code which uses reflection instead of dynamic:

    public static T UnwrapProxy<T>(T proxy) {
       if(!ProxyUtil.IsProxy(proxy)) {
          return proxy;
       }
       try {
          const System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
          var proxyType = proxy.GetType();
          var instanceField = proxyType.GetField("__target", flags);
          var fieldValue = instanceField.GetValue(proxy);
          return (T) fieldValue;
       }
       catch(RuntimeBinderException) {
          return proxy;
       }
    }
    
    0 讨论(0)
  • 2020-12-06 19:25

    This question is a little old but hopefully my solution (which relies on .NET 4+) will help someone.

    Having created a proxy as follows:

    ProxyGenerator generator = new ProxyGenerator();
    MyClass proxy = generator.CreateClassProxyWithTarget(underlying, new MyInterceptor(this));
    

    I have been able to get the underlying target with the following method:

    internal static TType UnwrapProxy<TType>(TType proxy)
    {
        if (!ProxyUtil.IsProxy(proxy))
            return proxy;
    
        try
        {
            dynamic dynamicProxy = proxy;
            return dynamicProxy.__target;
        }
        catch (RuntimeBinderException)
        {
            return proxy;
        }
    }
    

    It relies on the internal implementation of Castle - i.e. that the generated proxy has a __target member. It is nice and self contained though and backed up with a unit test or two, we should catch any changes should a later version of Castle break this. This is using v3.2.0.0 of Castle.

    0 讨论(0)
  • 2020-12-06 19:29

    I simply use an interface like this

    public interface IMarker
    {
      Type ActualType { get; }
    }
    

    add it to my proxy and intercept it:

    public class MyInterceptor<T> : IInterceptor
    

    ...

    if (invocation.Method.DeclaringType == typeof(IMarker))
    {
      if (invocation.Method.Name.Equals("get_ActualType"))
      {
        invocation.ReturnValue = typeof(T);
        return;
      }
    }
    

    So in the end i only have to check

    if( obj is IMarker ) 
      Type t = (obj as IMarker).ActualType`
    

    Maybe there are better options to do it, but it works and keeps my code clean from castle references. Hope this helps.

    0 讨论(0)
提交回复
热议问题