CastleDynamic 只获取虚拟值
CastleDynamic only get the virtual values
在测试 Castle DynamicProxy 时,我发现了一个奇怪的行为
我没有找到好的文档,所以我找到的更接近的信息是theses 2 问
Castle Dynamic Proxy not intercepting method calls when invoked from within the class
和
Why 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
。该对象将有自己的值 VirtualString
和 NonVirtualString
。 VirtualString
将被库覆盖以使用拦截器,但 NonVirtualString
不会被覆盖并将保持为 NULL,因为它是字符串的默认值。
您可以尝试改用接口拦截。否则,您将无法拦截非虚拟 methods/properties.
在测试 Castle DynamicProxy 时,我发现了一个奇怪的行为
我没有找到好的文档,所以我找到的更接近的信息是theses 2 问 Castle Dynamic Proxy not intercepting method calls when invoked from within the class 和 Why 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
。该对象将有自己的值 VirtualString
和 NonVirtualString
。 VirtualString
将被库覆盖以使用拦截器,但 NonVirtualString
不会被覆盖并将保持为 NULL,因为它是字符串的默认值。
您可以尝试改用接口拦截。否则,您将无法拦截非虚拟 methods/properties.