Tools like PostSharp, that manipulate the IL, can seem like black magic at first. However, the simple act of opening a decompiler changes all that. In this episode, Matt Groves shows how to decompile a .NET assembly and view code with/without a PostSharp aspect using Reflector to see exactly what’s being manipulated.
Q: In your previous session, you used aspect boundaries to do something that could also be accomplished by method interception. What factors help to decide which way you should implement?
A: The OnMethodBoundaryAspect offers higher performance because only a part of the calling context needs to be passed to the aspect. This is especially true with the aspect optimizer feature, included in PostSharp Pro and Ultimate, when the aspect does not consume a lot of context, for instance a transaction scope aspect. The benefit is reduced however if the aspect consumes a lot of context, for instance all argument values. The MethodInterceptionAspect is more powerful: you can invoke the intercepted method on a different thread, for instance. But it is slower because the whole calling context needs to be stored to the heap and passed to the aspect.
Q: How can I disable a PostSharp aspect temporarily?
A: There are a number of ways to disable PostSharp from a specific project:
In Visual Studio, open the project properties dialog, select the right configuration, open the PostSharp tab page, and change the value of the Disable PostSharp option.
In Visual Studio, open the project properties dialog, select the right configuration, open the Build tab page, and add the conditional compilation symbol SkipPostSharp.
Define the MSBuild property SkipPostSharp=True, for instance using the command line msbuild /p:SkipPostSharp=True.
Q: Which Aspects are serialized?
A: Every aspect is serialized at compile time. You can find out more on aspect serialization in PostSharp documentation.
Q: Is there deserialization during run-time?
A: Yes, by using a decompiler you will see that PostSharp stores serialized aspects as resources, for instance the aspect I applied to the DoSomething method in the video, and an internal class does the work of deserializing the resources into an object.
Q: Why are you using the objects (internal classes) instead of writing the code directly in the corresponding methods? Wouldn't that be more performant?
A: This approach is named “aspect inlining”. It is more performant but more complex and less powerful (aspects code would need to be more limited).
Q: System.Diagnostics.Contracts also uses the post-compiler rewrite method to check state and assertions. Do PostSharp and Contracts work well together?
A: Yes, they work well together. PostSharp runs after Code Contracts.
Q: It’s evident that PostSharp is heavily dependent on using .NET's underlying support for discovering and calling methods using Reflection. Are there any significant trade-offs or compromises in using Reflection so heavily?
A: PostSharp does not rely on reflection to discover and call methods. The analysis is done completely at build time, and PostSharp generates code to call exactly the right methods. Reflection is only used if the aspects themselves use reflection. Even then, any use of reflection is optimized and cached.
Up next: Unit Testing & Thin Aspects
The benefits of unit testing are numerous. When aspects are involved, Matt believes keeping them "thin" is key to keeping your code easy to unit test. Join us this Thursday as he explores some of the implications of unit testing when a post-compiler tool is involved.
During this final episode in the AOP in .NET series, Matt will be joined by Gael Fraiteur, the creator of PostSharp, who has a differing opinion about the relevancy of "thin" aspects and will speak about a set of practices that can be used to create efficient tests of aspects.
The generous folks at Manning Publications are offering a 40% discount on Matt’s new book to all live webinar attendees. So, if you want to learn what difference AOP and PostSharp can make in your projects, and take advantage of Manning’s discount offer, be sure to join us for the last live webinar in this series.
Seats are limited and this head-to-head episode is sure to sell out so reserve your spot today.
Matthew Groves delivered part 3 of his 5-part live webinar series on AOP in .NET recently. The series covers insights found in his new book and a variety of real-world coding examples using PostSharp.
In part 3, Matt looks at a real-world application of a method boundary aspect to help with caching.– followed by a Q&A session.
Q: Is OnExit always executed and, if yes, is it before or after OnSucess or OnException?
A: Imagine an invisible Try, Catch and Finally surrounding your method, then picture OnExit as being inside the Finally block of that imaginary Try/Catch block.
I say imaginary but, in the next episode, we will look at decompile and assembly and you’ll see there is a real Try, Catch and Finally block being generated by PostSharp. So, OnExit will run after OnSuccess because the code and Finally runs after the code inside the Try block.
Q: In the cache example is the data saved in the cache again, and is OnSucess even called or is it skipped because of the FlowBehavior?
A: When we set FlowBehavior to return that means OnSuccess, OnExit and OnException won’t be called at all. It will just return immediately and those boundaries won’t be executed, and it won’t be stored in the cache again.
Q: Instead of using a Cache object instantiated inside the aspect, is it possible to inject an implementation of it?
A: In my example I tightly coupled an aspect to a specific caching framework [ASP.NET cache]. If you’re suggesting I should inject a dependency so I’m working against an interface instead of directly against the ASP.NET cache, I agree with you. We’ll talk more about that in the upcoming unit testing episode, because an important part of unit testing is not having those elements be tightly coupled.
Q: How do we refresh the cache? Say if the value we are pulling from DB (say Median income) is changing every 10-15 minutes how can I keep my data up to date?
A: The answer depends on the caching framework you’re using. With ASP.NET cache it has a default expiration of around 20 minutes. You can change that if you’d like. In my example I set the cacheKey directly by writing:
HttpContext.Current.Cache[cacheKey] = args.ReturnValue
You can also use the Add method:
Here I can add the key, the value, CacheDependency, absoluteExpiration time, slidingExpiration time, Priority, etc. So if the median income caches often, you may want to set it to expire more frequently than every 20 minutes.
Q: Are there some useful pre-built caching aspects in PostSharp?
A: PostSharp 3 currently offers ready-made aspects to handle logging, INotifyPropertyChanged and multithreading. Ready-made caching is on the horizon. In the meantime, you may want to look at Attribute Based Caching, found on CodePlex, which uses PostSharp to handle many of the implementation practices talked about today.
Q: In your upcoming book, will the examples/code work in PostSharp 2.1 or is the latest version 3 required?
A: When I started writing the book PostSharp 3 wasn’t released yet so I mostly used version 2.1 to write the code. The coding examples however should work fine in either version.
Up next: Matt Groves goes Under the Hood of a Post-Compiler, showing how to decompile a .NET assembly and view code with and without a PostSharp aspect with Reflector.
Matthew Groves delivered part 2 of his 5-part live webinar series on AOP in .NET recently to support his upcoming book Aspect Oriented Programming in .NET, out from Manning Publications in June. The series covers insights found in his book and a variety of real-world coding examples using PostSharp.
In part 2, Matt demonstrates the method interception aspect, and looks at a real-world application of the aspect that can help with data transactions – followed by a lively Q&A session.
Q: With the use of Aspect Interceptors, does the behavior of stepping through and debugging the code in either the Interceptor or calling code change? If so, how?
A: With PostSharp, debugging works great! When PostSharp rewrites your code with IL manipulation it also makes appropriate changes to the debugging file. Which means, if you set a breakpoint in an aspect or in a method that has an aspect on it, that breakpoint will be hit when expected and you’ll get the full stack with that as well.
Q: Can you put a PostSharp attribute on an aspect’s method?
Q: Can we apply interceptors globally to all the methods in a class?
A: Absolutely. You can apply the attribute to the class and by default it will be applied to every method within that class. There are lots of customization available with PostSharp. You can customize how you want the attributes to be applied – even at assembly level.
Q: Is it possible to apply an aspect to DLL methods to which you don’t have the source?
A: In theory yes, but this scenario is not supported so you will be on your own in case of problem.
Q: Can we apply multiple aspects to a given method, and in what order are they executed?
A: In some situations, for instance if you have caching and authorization, the order in which the aspect is applied is very important. PostSharp gives us a few ways to deal with that. The simplest one is called AspectPriority where you specify a number to indicate the order in which aspects are run, and there are more robust features that PostSharp has as well to manage dependencies between aspects and aspect composition.
Q: What are some other examples of practical uses of aspects?
A: Logging, data transactions, caching, INotifyPropertyChanged, exception handling, authorization, validation, etc. In fact, PostSharp Ultimate comes with a whole suite of aspects that have been written for you. It’s a new feature in PostSharp 3 so you don’t have to spend time writing these aspects and can simply drop them in and start using them right away.
Q: Can you add an Attribute to a parent object and have it apply to all child objects?
A: Yes, using aspect inheritance.
Q: Will you show how to TDD aspects in this series, and do you show it in your book?
A: Not TDD specifically, but I have dedicated an entire chapter of my book to unit testing aspects and episode 5 in the series (May 30th) will focus on that.
Q: Does the aspect class name need to end with Attribute, as per .NET convention?
A: No, it’s not necessary. As long as you inherit from the Attribute base class, .NET will recognize it as an Attribute.
Q: Can you use PostSharp in Windows Phone 7 applications?
Q: What are the best practices for bringing dependencies into aspects?
A: That question will be covered at length during the Unit Testing Aspects episode on May 30th.
Q: When will your book be published?
A: June 14th.
If you want to ask Matt any question you may have about AOP in .NET and/or PostSharp be sure to sign-up for the series and join us every Thursday throughout the month of May.