Castle DynamicProxy: Get unproxied object

久未见 提交于 2019-12-17 16:49:06

问题


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 suggested to use the ProxyUtil class like this:

object realInstance = ProxyUtil.GetUnproxiedInstance(proxyInstance);

This does not seem to work as

bool isProxy = ProxyUtil.IsProxy(realInstance);

is always true.

I also tried using the following code snippet, which is essentially what ProxyUtil is doing:

var accessor = proxyInstance as IProxyTargetAccessor;
var realInstance = accessor.DynProxyGetTarget();

with the same results, realInstance is still a proxy.

What am I missing here?


回答1:


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.




回答2:


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



回答3:


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.




回答4:


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



来源:https://stackoverflow.com/questions/11082911/castle-dynamicproxy-get-unproxied-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!