DynamicProxy Lock: Get Unforgiven Object

I use Castle DynamicProxy to add an interceptor to my types. Now I need to get the base type (NOT the proxy itself).

I found some SO tips that suggested using the ProxyUtil class as follows:

object realInstance = ProxyUtil.GetUnproxiedInstance(proxyInstance); 

It doesn’t work like

 bool isProxy = ProxyUtil.IsProxy(realInstance); 

always true.

I also tried using the following code snippet, which essentially ProxyUtil does:

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

with the same results, realInstance is still a proxy server.

What am I missing here?

+6
source share
4 answers

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

By creating a proxy server as follows:

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

I managed to get the basic goal in the following way:

 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 Castle's internal implementation β€” that is, the generated proxy has the __target member. It's nice and self-sufficient, and with the support of a unit test or two, we have to catch any changes if a later version of Castle breaks this. It uses Castle v3.2.0.0.

+9
source

I just use this interface

 public interface IMarker { Type ActualType { get; } } 

add it to your proxy server 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 need to check

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

There may be better options for this, but it works and keeps my code clean from lock references. Hope this helps.

+1
source

If you are creating a proxy server based on inheritance ( generator.CreateClassProxy<MyClass>() ), the proxy is .

+1
source

If you do not have an invocation object available or you observe that 'Castle.Proxies.IXeroServiceProxy.__target' is inaccessible due to its protection level when trying to @ s1mm0t answer , you can try the following code that 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
source

Source: https://habr.com/ru/post/918357/


All Articles