Introduction
People who use NHibernate know that in order to take advantage of its lazy-loading facility, all public members of the persisted classes must be marked as virtual
. Compared to all the benefits the lazy-loading brings, this seems to be a very insignificant price. However, for some people, including me, this extra virtual
keyword is still some annoyance. It is very easy to forget about it when writing a new code, it makes Resharper complain sometimes ("virtual member call in constructor" warning), and it is ugly (subjective one, I know). In this article, I would like to show how to solve these issues with a simple Aspect that makes members virtual
even if the keyword is not used in the source code.
Background
The solution presented in this article is most useful to people using NHibernate (also indirectly via Active Record). If you don't know what NHibernate is, I would recommend checking it out here.
Using the Aspect
In order to use the Aspect, you will first need to download and install PostSharp. The remaining part of the article assumes that PostSharp is installed with the MSBuild integration enabled.
Download Unsealer, and copy the Unsealer.Weaver.dll and Unsealer.psplugin files into the Plugins directory under your PostSharp installation folder. Copy the Unsealer.dll into the folder where you keep the external libraries for your solution.
Open Visual Studio, and add the following references to the project that contains your persistent classes:
- PostSharp.Public.dll
- Unsealer.dll
At this point, Unsealer is enabled on the project. Now, you can either:
- Decorate every persistent class with the
[Unseal]
attribute, or - Use a shortcut, and add the:
[assembly: Unseal(AttributeTargetTypes = "*")]
line to the AssemblyInfo.cs file. This will allow you to forget about the virtual
at all.
This is it - the keyword can be removed from the classes. NHibernate will continue to run as if nothing changed, and if you inspect the DLL with Reflector, you will see that all public members are virtual.
Notes
Although the name of the Aspect is Unsealer, it does not remove the sealed
keyword from the methods. Actually, it causes the build to fail if the [Unseal]
attribute is used on a class that has sealed
members (or is sealed
itself). This is because I assume that the sealed
keyword is always used on purpose - as opposed to virtual
, which may be skipped accidentally.