I have 2 classes, one for accessing the database and child class with caching. I can change the source code of both classes but there are many classes with different structure so I'm looking for a way to make generic solution that will help me to intercept only methods I marked with the Attribute
or otherwise.
Here is an example
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 {}
I'm trying to use invocation.Method.GetCustomAttributes()
for myCondition
and mark only base class methods but the problem is that when the ChildClass.GetByKey()
invokes the base class method it does not intercept with MyInterceptor.Intercept()
method.
I can replace the inheritance with decomposition for this example but then I'll need to implement GetAll
and GetByName
methods in ChildClass
and this solution will not be generic.
How can I change ProxyGenerator
settings or CreateProxy()
method to solve my problem?
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);