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);
A base.Method call deliberately doesn't try to find any method overload that's further down the inheritance relationship than the base class of this. The proxy doesn't perform fancy magic, it overrides the method in a subclass and relies on the virtual call to reach the proxy rather than its base implementations. Or if it is a wrapping proxy, it only intercepts external calls - I don't know the details of your used proxy type.
So basically, you can't expect any sub-class magic to happen once you write base.Method. You will need to re-visit your design approach if you need interception within hierarchy-internal child-parent interaction.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With