【问题标题】:CastleDynamic only get the virtual valuesCastleDynamic 只获取虚拟值
【发布时间】:2018-06-19 02:42:20
【问题描述】:

我在测试 Castle DynamicProxy 时发现了一个奇怪的行为

我没有找到好的文档,所以我找到的更接近的信息是论文 2 问 Castle Dynamic Proxy not intercepting method calls when invoked from within the classWhy won't DynamicProxy's interceptor get called for *each* virtual method call?

有了它,我想,当你使用 CreateClassProxyWithTarget 时,一切都会进入 Class 并返回代理,所以如果 Prop/function 不是虚拟的,它只会返回 Class 值.

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

假设我有这段代码

主要

private static void Main(string[] args)
{
    var theObj = new SomeClass
    {
        NonVirtualString = "Non virtual value",
        VirtualString = "Virtual value"
    };
    var theProxy = Interceptor.AddProxy(theObj);

    Console.WriteLine($"OBJ NonVirtualString: {theObj.NonVirtualString } || VisrtualString {theObj.VirtualString }");
    Console.WriteLine($"Proxy NonVirtualString: {theProxy.NonVirtualString } || VisrtualString {theProxy.VirtualString }");
}


public class SomeClass
{
    public string NonVirtualString { get; set; }
    public virtual string VirtualString { get; set; }
}

拦截器

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

结果是

OBJ NonVirtualString: 非虚值 || VisrtualString 虚值

拦截:get_VirtualString with value: Virtual value

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

预期的结果是

OBJ NonVirtualString: 非虚值 || VisrtualString 虚值

拦截:get_VirtualString with value: Virtual value

Proxy NonVirtualString:非虚值 || VisrtualString 虚值

所以,如果结果是正确的,我该怎么办,我正在尝试使用 Castle 或其他 Lib(仅覆盖虚拟并保持非虚拟可访问?

【问题讨论】:

    标签: c# castle-dynamicproxy dynamic-proxy


    【解决方案1】:

    你可能做不到。无论如何,不​​是基于组合的CreateClassProxyWithTarget。当您在此类代理对象上调用非虚拟方法时,您完全绕过了 DynamicProxy;它无法拦截该调用,因此不会将其转发给目标对象。因此,您可以取回代理对象自己未初始化的 NonVirtualString 属性的值。

    你可以让它与基于继承的代理一起工作,即CreateClassProxy。使用这种方法,您将只有一个对象(代理)而不是两个,因此您可以直接在代理对象上设置属性值,而不是在单独的目标上。然后,即使 DynamicProxy 仍然无法拦截对 NonVirtualString 的 getter 的调用,该调用将只使用原始类的 getter。

    【讨论】:

      【解决方案2】:

      因为该属性不是虚拟的,所以代理类不能覆盖它。当您调用Interceptor.AddProxy() 时,它会创建一个继承自SomeClass 的类型的new 对象。该对象将有自己的值VirtualStringNonVirtualStringVirtualString 将被库覆盖以使用 Interceptor,但 NonVirtualString 不会被覆盖并保持为 NULL,因为它是字符串的默认值。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-13
        • 2015-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多