Background
Unlike Java, in .NET, it is not easy to find discussion about AOP or actual application. Personally, the biggest reason is that .NET is inconvenient to apply the Weaving technique to bring the AOP perspective into the actual runtime.
In case of Java, you can freely redefine the methods of the required implementation class by inheriting the class, unless you are not constrained to it. However, in the case of .NET, unless you consider the virtual method, delegate, or decorator pattern in advance, you need to prepare at the tool level to create the desired AOP concept.
As I learn Java, Spring, and AspectJ, I try to find a different language about AOP and a corresponding implementation of .NET. I have a meaningful library and write a simple article. It is a library called NConcern
.
NConcern
works much like the Java AOP framework. It provides the same functionality as PostSharp's Compile Time Weaving and Runtime Weaving. Compile Time Weaving is especially supported by the CNeptune
library, which is based on Mono's Cecil library.
Unfortunately, as of April 2017, NConcern
does not support .NET Core, but only supports projects with .NET Framework 4.0 or later. There is a compatibility issue preventing Visual Studio for mac from using this library, and the bug will be fixed soon.
Trying NConcern
To see how NConcern
works, create a simple Console Application project in Visual Studio. After creating the project, add the following two packages as NuGet Package Manager.
Note that you can only install NConcern
if you are not using Compile Time Weaving and you are only using Runtime Weaving. However, what you want to talk about in this article is Compile Time Weaving, so you need to install and test CNeptune
.
After successfully installing the package, make sure that the following changes have been made to the packages.config file:
="1.0″ encoding="
<packages>
<package id="CNeptune" version="1.0.6″ targetFramework="net452″ />
<package id="NConcern" version="4.0.2″ targetFramework="net452″ />
</packages>
Now create a class for testing purposes.
public sealed class Sample
{
public void Test()
{
Console.WriteLine("Hello, World!");
}
}
As you can see, this class is declared as sealed
keyword and cannot be inherited. In addition, the Test
method is not a virtual method and cannot be overridden.
Next, I will add a Logging Aspect for logging purposes.
public class Logging : IAspect
{
public IEnumerable<IAdvice> Advise(MethodBase method)
{
yield return Advice.Basic.Before((instance, arguments) =>
{
Console.WriteLine($"Before {method.Name}({String.Join(", ", arguments)})");
});
yield return Advice.Basic.After((instance, arguments) =>
{
Console.WriteLine($"After {method.Name}({String.Join(", ", arguments)})");
});
}
}
Now let's add code to weaving the Logging Aspect. It does not match an attribute or an interface. It simply instructs the method to weave the Logging Aspect for a method named "Test
". The following code instantiates the Sample
class and calls the Test
method.
class Program
{
static void Main(string[] args)
{
Aspect.Weave<Logging>(x => x.Name == "Test");
var test = new Sample();
test.Test();
}
}
And when you compile and run this code, you get the following expected results:
Before Test()
Hello, World!
After Test()
Press any key to continue . .
What Has Changed
When you install the CNeptune
package, the procedure to rewrite the assembly so that Compile Time weaving the assemblies it creates becomes part of the MSBUILD
project. When you open the CSPROJ file of the project where the package is installed, you can see the following section added.
<Import Project="..\packages\CNeptune.1.0.6\build\CNeptune.targets"
Condition="Exists(‘..\packages\CNeptune.1.0.6\build\CNeptune.targets’)" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer.
Use NuGet Package Restore to download them. For more information,
see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists(‘..\packages\CNeptune.1.0.6\build\CNeptune.targets’)"
Text="$([System.String]::Format(‘$(ErrorText)’,
‘..\packages\CNeptune.1.0.6\build\CNeptune.targets’))" />
</Target>
Unlike the IL code generated by the compiler, the IL code thus generated is exported in a form that is easy to redefine. Whether or not you actually call Weaving, you are calling CNeptune
via MSBUILD
, so the output of the assembly will be different than before the CNeptune
package is applied.
Conclusion
Although it is processing at compile time, it is free to apply and release weaving. In the sample code above, add the following additional code to the Main
method, and the results will be displayed as you intended.
Console.WriteLine();
Aspect.Release<Logging>(x => x.Name == "Test");
test.Test();
Before Test()
Hello, World!
After Test()
Hello, World!
In this way, .NET has been able to use the open source AOP framework. NConcern
and CNeptune
are both MIT licenses and can be applied to commercial projects without worrying about licensing.
If you would like to find out more about the CNeptune
and NConcern
projects, or to provide feedback and enhancements to these projects, I encourage you to explore the GitHub link below.
History
- 2017-05-07: Adding GitHub URL of CNeptune and NConcern Project
- 2017-05-06: First edition