【发布时间】:2018-07-04 23:29:49
【问题描述】:
我有 2 个类,一个用于访问数据库和具有缓存的子类。我可以更改这两个类的源代码,但是有许多具有不同结构的类,所以我正在寻找一种方法来制作通用解决方案,以帮助我只拦截我用Attribute 或其他方式标记的方法。
这是一个例子
public class BaseClass
{
[MyAttribute]
public virtual MyEntity[] GetAll() {}
[MyAttribute]
public virtual MyEntity GetByKey(int key) {}
[MyAttribute]
public virtual void GetByName(string name) {}
}
public class ChildClass : BaseClass
{
public override MyEntity GetByKey(int key)
{
if(key > 100)
return GetCachedEntity(key);
return base.GetByKey(key);
}
}
public class MyInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
// Here I can check any required conditions to decide on the way of processing
var myCondition = invocation.Method.GetCustomAttributes(false).Any(a => a is MyAttribute);
if(myCondition)
{
// extra logic for marked methods
}
invocation.Proceed();
}
}
public static class MyProxyFactory
{
private static readonly ProxyGenerator proxyGenerator = new ProxyGenerator();
// here is my generic proxy factory which I want to use for creating proxies for ChildClass objects and another objects that contains similar logic
public static TInterface CreateProxy<TInterface>(TInterface concreteObject)
where TInterface : class
{
var proxy = proxyGenerator.CreateInterfaceProxyWithTarget(concreteObject, ProxyGenerationOptions.Default, new MyInterceptor());
return proxy;
}
}
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class MyAttribute : Attribute {}
我正在尝试将invocation.Method.GetCustomAttributes() 用于myCondition 并仅标记基类方法,但问题是当ChildClass.GetByKey() 调用基类方法时,它不会使用MyInterceptor.Intercept() 方法进行拦截。
对于这个例子,我可以用分解替换继承,但是我需要在ChildClass 中实现GetAll 和GetByName 方法,这个解决方案将不是通用的。
如何更改ProxyGenerator 设置或CreateProxy() 方法来解决我的问题?
var realObject = new ChildClass();
var proxyObject = MyProxyFactory.CreateProxy(realObject);
// extra logic should be executed
proxyObject.GetAll();
// extra logic should be executed
proxyObject.GetByKey(99);
// extra logic should not be executed
proxyObject.GetByKey(101);
【问题讨论】:
-
也许你应该添加一些代码来测试和证明你想说的话
-
@NSGaga 我在问题末尾添加了代码。您可以假设 MyInterceptor 中的额外逻辑包含
Console.WriteLine("query to database was executed")然后proxyObject.GetByKey(99);应该在控制台上写入此消息而proxyObject.GetByKey(101);不应该。
标签: c# system.reflection castle-dynamicproxy