.net 城堡动力:获得未经腐蚀的物体

.net 城堡动力:获得未经腐蚀的物体,.net,castle-dynamicproxy,.net,Castle Dynamicproxy,我正在使用Castle DynamicProxy向我的类型添加拦截器。 现在我需要获取底层的基类型(而不是代理本身) 我在上找到了一些提示,建议使用ProxyUtil类,如下所示: object realInstance = ProxyUtil.GetUnproxiedInstance(proxyInstance); 这似乎不起作用 bool isProxy = ProxyUtil.IsProxy(realInstance); 这永远是真的 我还尝试使用以下代码段,这基本上就是ProxyUt

我正在使用Castle DynamicProxy向我的类型添加拦截器。 现在我需要获取底层的基类型(而不是代理本身)

我在上找到了一些提示,建议使用ProxyUtil类,如下所示:

object realInstance = ProxyUtil.GetUnproxiedInstance(proxyInstance);
这似乎不起作用

bool isProxy = ProxyUtil.IsProxy(realInstance);
这永远是真的

我还尝试使用以下代码段,这基本上就是ProxyUtil所做的:

var accessor = proxyInstance as IProxyTargetAccessor;
var realInstance = accessor.DynProxyGetTarget();
在相同的结果下,realInstance仍然是一个代理


我缺少什么?

我只是使用这样一个界面

public interface IMarker
{
  Type ActualType { get; }
}
将其添加到我的代理并拦截它:

public class MyInterceptor<T> : IInterceptor
所以最后我只需要检查一下

if( obj is IMarker ) 
  Type t = (obj as IMarker).ActualType`
也许有更好的选择可以做到这一点,但它可以使我的代码不受castle引用的影响。
希望这有帮助。

如果您正在构建一个基于继承的代理(
generator.CreateClassProxy()
),那么代理就是目标。

这个问题有点老了,但希望我的解决方案(依赖.NET 4+)能帮助别人

创建了一个代理,如下所示:

ProxyGenerator generator = new ProxyGenerator();
MyClass proxy = generator.CreateClassProxyWithTarget(underlying, new MyInterceptor(this));
我已经能够通过以下方法获得底层目标:

internal static TType UnwrapProxy<TType>(TType proxy)
{
    if (!ProxyUtil.IsProxy(proxy))
        return proxy;

    try
    {
        dynamic dynamicProxy = proxy;
        return dynamicProxy.__target;
    }
    catch (RuntimeBinderException)
    {
        return proxy;
    }
}
内部静态TType(TType代理)
{
如果(!ProxyUtil.IsProxy(代理))
返回代理;
尝试
{
动态dynamicProxy=代理;
返回dynamicProxy.\u目标;
}
捕获(RuntimeBinderException)
{
返回代理;
}
}

它依赖于Castle的内部实现,即生成的代理有一个__目标成员。虽然它很好,并且是独立的,并且有一两个单元测试作为备份,但是如果Castle的更高版本打破了这一点,我们应该能够捕捉到任何变化。这是使用Castle的v3.2.0.0。

如果您没有可用的
调用
对象,或者如果您在尝试@s1mm0t的答案时观察到
'Castle.Proxies.IXeroServiceProxy.\uu目标由于其保护级别
而无法访问,您可以尝试以下使用反射而不是
动态
的代码:

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;
   }
}
公共静态T展开路径(T代理){
如果(!ProxyUtil.IsProxy(代理)){
返回代理;
}
试一试{
const System.Reflection.BindingFlags flags=System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
var proxyType=proxy.GetType();
var instanceField=proxyType.GetField(“\uu目标”,标志);
var fieldValue=instanceField.GetValue(代理);
返回(T)字段值;
}
捕获(RuntimeBinderException){
返回代理;
}
}

我正在使用
CreateClassProxyWithTarget(实例,拦截器)
创建代理。问题在于NHibernate失败了,因为它认为它应该映射代理,而不是目标。
dynamic
在这里获胜。总比试图反省强。这是一次史诗般的失败。截至撰写之日(即2019年4月14日),此答案中的代码导致
“Castle.Proxies.IXeroServiceProxy.\uu目标”由于其保护级别而无法访问。我不会投反对票,因为它可能在当时使用了不同版本的
dynamic
实现以及类
DynamicProxy
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;
   }
}