Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Just Another .NET AOP Framework: NConcern

5.00/5 (7 votes)
7 May 2017CPOL3 min read 26.3K  
Introducing NConcern, a free open source compile-time AOP framework

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.

  • CNeptune
  • NConcern

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:

XML
<?xml version="1.0″ encoding="utf-8″?>
<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.

C#
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.

C#
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.

C#
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.

HTML
<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.

C#
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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)