namespace DynamicInterception
{
public class Calculator
{
public virtual int Div(int a, int b)
{
try
{
return a / b;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
return 0;
}
}
}
[Serializable]
public abstract class Interceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
ExecuteBefore(invocation);
invocation.Proceed();
ExecuteAfter(invocation);
}
protected abstract void ExecuteAfter(IInvocation invocation);
protected abstract void ExecuteBefore(IInvocation invocation);
}
public class CalculatorInterceptor : Interceptor
{
protected override void ExecuteBefore(Castle.DynamicProxy.IInvocation invocation)
{
Console.WriteLine("Start: {0}", invocation.Method.Name);
}
protected override void ExecuteAfter(Castle.DynamicProxy.IInvocation invocation)
{
Console.WriteLine("End: {0}", invocation.Method.Name);
}
}
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
Calculator c = generator.CreateClassProxy<Calculator>(new CalculatorInterceptor());
var r = c.Div(11, 0);
Console.ReadKey();
}
}
}
Is it possible to replace public virtual int Div(int a,int b)
with interface
interface ICalculator
{
int Div(int a, int b);
}
How then should look like proxy declaration?
ProxyGenerator generator = new ProxyGenerator();
Calculator c = generator.CreateClassProxy<Calculator>(new CalculatorInterceptor());
If you want to add an interface to the Calculator
and to execute those 2 lines
it will work the same:
public interface ICalculator
{
int Div(int a, int b);
}
public class Calculator : ICalculator
{
public int Div(int a, int b)
{
try
{
return a / b;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
return 0;
}
}
}
ProxyGenerator generator = new ProxyGenerator();
Calculator c = generator.CreateClassProxy<Calculator>(new CalculatorInterceptor());
But you didn't really do anything by that - you are still creating the proxy for a concrete derived type. I assume you want something like "CreateClassProxy<ICalculator>"
. That won't work because the CreateClassProxy
has a generic constraint on where TClass : class
.
What you do have is a variety of CreateInterfaceProxt..
Methods which you can try. But still a naive execution like the following won't work:
ICalculator c = generator.CreateInterfaceProxyWithoutTarget<ICalculator>(new CalculatorInterceptor());
c.Div(1, 2);
It will execute, call the interceptor and will fail when running the invocation.Proceed();
with the error:
System.NotImplementedException This is a DynamicProxy2 error: The interceptor attempted to 'Proceed' for method 'Int32 Div(Int32, Int32)' which has no target. When calling method without target there is no implementation to 'proceed' to and it is the responsibility of the interceptor to mimic the implementation (set return value, out arguments etc)
So as the good indicative (seriously) errors of Castle specify - you must somehow have an implementation for it - or by indicating it yourself in the interceptor - of by having a Component
registered for that interface.
Instead you can do like this: (Check comments in code)
ProxyGenerator generator = new ProxyGenerator();
ICalculator calculator = new Calculator();
var proxyCalculator = generator.CreateInterfaceProxyWithTarget(typeof(ICalculator),calculator, new CalculatorInterceptor());
calculator.Div(1, 2); // Will execute but will not be intercepted
((ICalculator)proxyCalculator).Div(11, 0); //Will execute and will be intercepted
But after saying all I said above, if the purpose behind all of this is to have an interceptor intercept your method then just just the "good-old" registering to the container:
WindsorContainer container = new WindsorContainer();
container.Register(
Component.For<CalculatorInterceptor>(),
Component.For<ICalculator>()
.ImplementedBy<Calculator>()
.Interceptors<CalculatorInterceptor>());
var calculator = container.Resolve<ICalculator>();
calculator.Div(1, 0);
// Output:
// Start: Div
// Attempted to divide by zero
// End: Div
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