CastleDynamic 只获取虚拟值

CastleDynamic only get the virtual values

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

我没有找到好的文档,所以我找到的更接近的信息是theses 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 不是虚拟的,它只是 return 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: Non virtual value || VisrtualString Virtual value

Intercepting: get_VirtualString with value: Virtual value

Proxy NonVirtualString: NULL || VisrtualString Virtual value

预期的结果是

OBJ NonVirtualString: Non virtual value || VisrtualString Virtual value

Intercepting: get_VirtualString with value: Virtual value

Proxy NonVirtualString: Non virtual value || VisrtualString Virtual value

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

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

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

的调用

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

您可以尝试改用接口拦截。否则,您将无法拦截非虚拟 methods/properties.