C# CastleDynamic仅获取虚拟值

C# CastleDynamic仅获取虚拟值,c#,castle-dynamicproxy,dynamic-proxy,C#,Castle Dynamicproxy,Dynamic Proxy,当我在测试城堡炸药时,我发现了一种奇怪的行为 我没有找到好的文档,所以我找到的更接近的信息是论文2 和 有了它,我假设,当您使用CreateClassProxyWithTarget时,所有内容都进入类并返回到代理,因此如果Prop/函数不是虚拟的,它只返回类值 我想,有了代码示例,我的问题就清楚了 让我们假设我有这个代码 主要 拦截器 public static class Interceptor { private static readonly ProxyGenerator _ge

当我在测试城堡炸药时,我发现了一种奇怪的行为

我没有找到好的文档,所以我找到的更接近的信息是论文2 和

有了它,我假设,当您使用CreateClassProxyWithTarget时,所有内容都进入类并返回到代理,因此如果Prop/函数不是虚拟的,它只返回类值

我想,有了代码示例,我的问题就清楚了

让我们假设我有这个代码

主要

拦截器

public static class Interceptor
{
    private static readonly ProxyGenerator _generator = new ProxyGenerator();

    public static TEntity AddProxy<TEntity>(TEntity entity) where TEntity: class, new()
    {
        var proxy = _generator.CreateClassProxyWithTarget(entity, new LogInterceptor());
        return proxy;
    }
}
结果是

OBJ非虚拟字符串:非虚拟值| |虚拟字符串虚拟值

拦截:使用值获取虚拟字符串:虚拟值

代理非虚拟字符串:NULL| | VisrtualString虚拟值

预期的结果是

OBJ非虚拟字符串:非虚拟值| |虚拟字符串虚拟值

拦截:使用值获取虚拟字符串:虚拟值

代理非虚拟字符串:非虚拟值| |虚拟字符串虚拟值


那么,如果结果是对的,我该怎么做,用Castle或其他Lib我正在尝试的东西(仅过度隐藏虚拟对象并保持非虚拟对象的可访问性?

您可能无法。无论如何,使用基于组合的
CreateClassProxyWithTarget
都不行。当您在这样的代理对象上调用非虚拟方法时,您完全绕过了DynamicProxy;它无法拦截该调用,因此不会阻止您的请求。)将其rd到目标对象。因此,您可以返回代理对象自身未初始化的
非虚拟字符串
属性的值


您可以使用基于继承的代理,即使用
CreateClassProxy
。使用这种方法,您将只有一个对象(代理)因此,您可以直接在代理对象上而不是在单独的目标上设置属性值,而不是两个。然后,即使DynamicProxy仍然无法截获对
非虚拟字符串的getter的调用,调用将只使用原始类的getter。

因为属性不是虚拟的,代理类也无法覆盖当您调用
Interceptor.AddProxy()时
它创建了一个从
SomeClass
继承的类型的新对象。此对象将有自己的
VirtualString
值,并且
NonVirtualString
将被库覆盖以使用拦截器,但
NonVirtualString
将不会被覆盖,并保持为空,因为这是字符串的默认值

您可以尝试改用接口拦截。否则,您将无法拦截非虚拟方法/属性

public static class Interceptor
{
    private static readonly ProxyGenerator _generator = new ProxyGenerator();

    public static TEntity AddProxy<TEntity>(TEntity entity) where TEntity: class, new()
    {
        var proxy = _generator.CreateClassProxyWithTarget(entity, new LogInterceptor());
        return proxy;
    }
}
[Serializable]
public class LogInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        try
        {
            invocation.Proceed();
            Console.WriteLine("Intercepting: {0} with value: {1}", invocation.Method.Name, invocation.ReturnValue);
        }
        catch (Exception ex)
        {
            Console.WriteLine(string.Format("Exception in method {0}{1}{2}", invocation.Method.Name,
                                            Environment.NewLine, ex.Message));
            throw;
        }
    }
}