Sometimes when working with C# you discover some hidden gems. Some of them very useful, other ones a little bit harder to find a good way to benefit from their functionality. One of those hidden gems that I discovered some days ago is the DispatchProxy class.
DispatchProxy is a new class in .NET Core that allows you to apply Aspect Oriented Programming techniques using interception.
Let’s try it out by creating a really simple LogInterceptor:
public class LogInterceptor<TInterface> : DispatchProxy | |
{ | |
private object _target = null; | |
protected override object Invoke(MethodInfo targetMethod, object[] args) | |
{ | |
Console.WriteLine("Before invoking targetMethod"); | |
var result = targetMethod.Invoke(_target, args); | |
Console.WriteLine("After invoking targetMethod"); | |
return result; | |
} | |
private void SetTarget(object target) | |
{ | |
_target = target; | |
} | |
public static TInterface Intercept<T>(T decorated) | |
{ | |
var proxy = Create<TInterface, LogInterceptor<TInterface>>(); | |
dynamic dynamicProxy = proxy; | |
dynamicProxy.SetTarget(decorated); | |
return proxy; | |
} | |
} |
The DispatchProxy class is a little cumbersome and we have to capture our target method using a little dynamic magic(casting would have worked as well):
dynamic dynamicProxy = proxy; | |
dynamicProxy.SetTarget(decorated); |
Now let’s create an interface and a corresponding implementation:
public class HelloWorld : ISayHello | |
{ | |
public string SayHello(string to) | |
{ | |
Console.WriteLine("Calling SayHello"); | |
return $"Saying hello to {to}"; | |
} | |
} |
public interface ISayHello | |
{ | |
string SayHello(string to); | |
} |
As a final step we create an intercepted version of our class and invoke our method:
static void Main(string[] args) | |
{ | |
var helloWorld = new HelloWorld(); | |
var helloWorldProxy = LogInterceptor<ISayHello>.Intercept(helloWorld); | |
helloWorldProxy.SayHello("everyone!"); | |
Console.ReadLine(); | |
} |
Here is our output: