Aspect Oriented Programming using proxies in ASP.NET Core

After working with Spring Boot for a couple of months now, one thing that I find lacking in ASP.NET Core (C#) is Aspect Oriented Programming (AOP).

In computing, aspect-oriented programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. It does so by adding additional behavior to existing code (an advice) without modifying the code itself, instead separately specifying which code is modified via a “pointcut” specification, such as “log all function calls when the function's name begins with ‘set’". This allows behaviors that are not central to the business logic (such as logging) to be added to a program without cluttering the code, core to the functionality. AOP forms a basis for aspect-oriented software development. – Wikipedia

There are a couple use cases where AOP can be used:

  • Logging or Auditing
  • Transactions management
  • Security (rarely)
The proxy pattern is also used for Mocking (e.g. Moq, NSubstitute, ...) and Lazy loading (e.g. EF Core, NHibernate, ...).

All the code in this blog post is demonstrated in this repository.

AOP in C#.

It's already possible to do AOP in C#, a quick search in Google will show you how: RealProxy and MarshalByRefObject. Technically, it can be used both locally and remotely, which is very nice until you understand that all your target objects must inherit MarshalByRefObject. That alone drives people to not even consider it.

The better way

Thankfully, there is a better way to create proxies of objects in C#, using Castle.DynamicProxy.

Castle DynamicProxy is a library for generating lightweight .NET proxies on the fly at runtime. Proxy objects allow calls to members of an object to be intercepted without modifying the code of the class. Both classes and interfaces can be proxied, however only virtual members can be intercepted. – Castle Project

Using Castle's dynamic proxies, you can create proxies of abstract classes, interfaces (while providing the implementation) and classes (only virtual methods/properties).

As an example, let's say we're making a server that handles blog posts:

Usually, you would register IBlogService with the implementation BlogService, and everything will work well. But now, you want to proxy the interface and do something whenever a method is called.

First, we need to create an interceptor that intercepts method calls, just like RealProxy:

Then, we'll create the proxy object using a generator:

We have now created a proxy object that implements IBlogService and has the inner implementation BlogService. Whenever an interface method is called, the LoggingInterceptor.Intercept method will be called and when it calls invocation.Proceed(), the implemented method in BlogService will be called.

Using it in ASP.NET Core

The idea here is to always serve proxies of services using the IOC Container of ASP.NET Core. Castle Project does have its own IOC Container Castle Windsor which makes injecting proxies much easier, but we won't use it for now.

First, we'll add a simple dependency to our LoggingInterceptor to show how we can handle them using DI. In reality, most of your interceptors will require one or more dependencies.

Second, we'll register a singleton ProxyGenerator and all the interceptors we're working with (LoggingInterceptor for now):

Lastly, we'll register everything:

Here's how it works:

  1. We register the implementation (e.g. BlogService). This is because the implementation might have dependencies that need to be resolved using DI, (there might be a better way).
  2. Whenever the interface is asked for:
    1. We get the instance of ProxyGenerator.
    2. We get an instance of the implementation.
    3. We get all the registered interceptors.
    4. We create and return a proxy of the interface with the inner implementation and the interceptors.

Now, whenever we ask for IBlogService, we'll receive a proxy object that passes through all the interceptors, and then call the actual methods in BlogService.

Unfortunately, this isn't very easy nor straightforward to do in ASP.NET Core compared to Spring, but we can easily turn this into a simple “framework”. We can hook into specific methods using Castle's DynamicProxy and do more advanced things.

I hope this helps some of you & Happy Coding!

Zanid Haytam Written by:

Zanid Haytam is an enthusiastic programmer that enjoys coding, reading code, hunting bugs and writing blog posts.

comments powered by Disqus