Posts tagged with 'DynamicProxy'

Welcome to another "Weekly Concerns". This is a post-a-week series of interesting links, relevant to programming and programmers. You can check out previous Weekly Concerns posts in the archive.

If you have an interesting link that you'd like to see in Weekly Concerns, leave a comment or contact me.

The Boise .NET User Group was kind enough to invite me to be a presenter. Boise is a bit too far away for me to make it there on a weekday on a small budget, but they were accomodating enough to allow me to present remotely. There were a couple minor technical issues, but mostly it went well. Even though I've done this presentation a lot, Brian cajoled me into talking about INotifyPropertyChanged, which is something I've only done once before during this talk (usually I'm constrained for time, or the group isn't interested in the MVVM pattern).

Brian Lagunas even made a recording of the presentation. The recording started a minute or so late, and it ending a couple minutes too early (the internet in the Boise location went down), but most of it is was recorded with Microsoft Live Meeting (not my favorite remote collaboration tool, but it was adequate). And now, it's on YouTube:

Slides and code are available in the AOP For You and Me GitHub repository.

Here's a quick example of how to write a caching aspect with Castle DynamicProxy.

First, let's write an implementation and a service worth caching:

Next, you need to decide where to cache the results. If you're using a web app, maybe try ASP.NET's Cache object. If you're writing an Azure app, try AppFabric caching. You can cache things in a database, a text file, whatever is appropriate for your application.

For this simple example, I'm going to cache everything in memory, in a static Dictionary object. Also, nothing that goes into my cache will ever expire or be invalidated. Once it's cached, it's cached forever. Also, it's not thread safe. Not a very useful cache in a real app, so let me just be clear: do not use this in a production application. It's only for demonstration: whatever you use for caching is up to you, I'm just demonstrating the aspect part.

I'm generating the cache key by appending the argument values to the method name. So if you call MyMethod("test") and MyMethod("test2"), that's two different keys that will cache two different results. This might work for you, or you might need a more complex GenerateCacheKey method (something that uniquely identifies objects, perhaps).

Next, I wire up my IoC container to return MyService when asked for an implementation of IMyService. But I also have to make sure that my IoC container (StructureMap in this case) applies the caching interceptor to it.

I put it all together in a simple console app:

And here's the result:

Console app with caching

Here's the last post in my series of AOP terminology posts.

This week's term is "weaving".

Weaving is a general term to describe how an AOP tool combines an aspect with the rest of your code.

There are two main methods of weaving:

  • Post-compiliation - modifying the code after the program already been compiled
  • Runtime - Modifying/replacing the code while the program is running

Castle DynamicProxy uses runtime weaving. You can think of it as just like using the decorator pattern, except instead of coding each decorator by hand, Castle DynamicProxy will create those classes for you at runtime, by combining the IInterceptor implementation (that you've created) with the object that you want to intercept.

PostSharp is a post-compiler tool. It will take the aspect class that you've defined and actually modify your compiled program to weave it in to the methods/properties/etc you want it to intercept. I think a good way to visualize this is by using a decompiler to see what the code looks like before and after PostSharp has modified it.

Here's a very basic console app with a single aspect applied to a single method.

Here's what it looks like after compiling with PostSharp turned off and then decompiling (I used ILSpy as the decompiling tool this time):

Here's what it looks like after compiling with PostSharp turned on and then decompiling:

Don't panic, it's not as complicated as it looks: don't let the weird naming throw you off. Notice line 23: that's the only line that I wrote inside of the DoStuff method. The rest all comes from the aspect. The try/catch/finally structure was all put in to place by PostSharp. The first line of the method now calls the OnEntry method that I defined in the aspect. The OnSuccess method is the last thing called inside the Try. The OnException is called inside of the Catch. And OnExit is called inside of the Finally. (Note: they all get null arguments because I don't actually do anything of value inside the aspect, otherwise you'd also see some code to create the argument objects to pass in).

You can see that even though your source code is separated out into two classes, PostSharp does the work of weaving the cross-cutting concerns into the other method.

I came across this question about interception vs injection on Programmer's Stack Exchange. Since I'm always blogging and talking about AOP, my thoughts immediately went to suggesting an AOP framework.

However, Mark Seeman wrote a very good answer about using the decorator pattern (or proxy pattern depending on how you look at it), and beyond being a good answer, it made me pause and think about the implications. If decorator/proxy combined with dependency injection does the job, why would I ever introduce an AOP tool?

Well, in many cases the answer is: I shouldn't! If I'm only applying cross-cutting concerns to a handful of classes, it's totally feasible for me to write out proxy/decorators and wire them up in my IoC container. Consider:

  • 2 service interfaces: ICustomerRepository and IProductRepository
  • 2 implementations: CustomerRepository and ProductRepository (which implement the interfaces respectively)
  • 2 logging decorators: CustomerLoggingDecorator and ProductLoggingDecorator (which also implement the interfaces respectively)
  • 2 caching decorators: CustomerCachingDecorator and ProductCachingDecorator (which also implement the interfaces respectively)

And there you go. No post-compile step, no runtime reflection generation, just you, 8 classes/interfaces and your IoC tool of choice. The logging and caching decorator classes could be very similar in their implementations, but it's not so bad, and I still get a nice separation of concerns, and all my implementations are single responsibility.

But now consider:

  • 100 service interfaces: ICustomerRepository, IProductRepository, and 98 others...
  • 100 service implementations: CustomerRepository, ProductRepository, and 98 others...
  • 100 logging decorators: CustomerLoggingDecorator, ProductLoggingDecorator, and 98 others...
  • 100 caching decorators: CustomerCachingDecorator, ProductCachingDecorator, and 98 others...

Whoa. Well, I still have a very nice separation of concerns, and I'm still following single responsibility. Wiring them up in a good IoC tool shouldn't be a problem, so long as I follow a good naming convention. So this isn't terrible.

But, now I have 400 classes/interfaces, most of which probably have very similar boilerplate code throughout. If I make a change to that boilerplate in one class, I have to change it in (possibly) 99 other classes. I still think this architecture is better than just tangling logging/caching code inside of the service implementations, it still leaves a lot to be desired.

Now consider an architecture using, say, Castle DynamicProxy:

  • 100 service interfaces: ICustomerRepository, IProductRepository, and 98 others...
  • 100 service implementations: CustomerRepository, ProductRepository, and 98 others...
  • 1 logging interceptor class: LoggingInterceptor
  • 1 caching interceptor class: CachingInterceptor

I think this is much better. No repetition with logging and caching decorators. I can still easily wire up the dependencies with a good IoC tool. If my logging or caching needs to change, I only need to change one place. If I actually need different logging or caching implementations, I can still do that. The only major difference is that now I have to use an AOP tool like DynamicProxy or PostSharp.

So, when should you use the decorator/proxy patterns and when should you use an AOP tool? With 2 service classes, you can definitely get by with your own decorators. With 100 service classes...maybe not so much. "Somewhere in between" is my weaselly answer.

  • If you know your app will have a ton of service classes, you may as well start with an AOP tool.
  • If you know your app will only have a small amount, you may as well stick to decorator/proxy.
  • If you aren't sure, start with decorator/proxy and move to an AOP tool when you feel like there's too much boilerplate and repetition.

If you plan your architecture carefully, you can switch back and forth between tool and tool-less with a minimum of effort.

Matthew D. Groves

About the Author

Matthew D. Groves lives in Central Ohio. He works remotely, loves to code, and is a Microsoft MVP.

Latest Comments

Twitter