I want to have an attribute like this for Cross Cutting Concerns like Logging , Exception , ...

public class MyService
{

[Log] // Interception (AOP)
[ExceptionHandler] // Interception (AOP)
public void DoSomething()
   {

   }
}

I know that I can write these codes with postsharp but I want to write these interceptions with free libraries like Castle Core and ...

Can anyone help me and write a sample for these purpose ??? I need a very simple sample for learning concepts

4

There are 4 best solutions below

0
On

This lib does what you need https://github.com/pamidur/aspect-injector

[LogCall]
public void Calculate() 
{ 
    Console.WriteLine("Calculated");
}

ps. shameless self-ad

0
On

if you want to use runtime aop , you can try https://fs7744.github.io/Norns.Urd/index.html

it is very simple, a Interceptor like:

public class ConsoleInterceptor : AbstractInterceptor
 {
     public override async Task InvokeAsync(AspectContext context, AsyncAspectDelegate next)
     {
         Console.WriteLine($"{context.Service.GetType().GetReflector().FullDisplayName}.{context.Method.GetReflector().DisplayName}");
         await next(context);
     }
 }
0
On

Autofac is a free IoC container. I use Autofac with Autofac.Extras.DynamicProxy2 nuget, docs.

Assuming you know why and when to (and not to) use interceptors, and you want to intercept some functionality:

public class FooService : IFooService
{
    public void MoreFoo()
    {
        DoSomething();
    }
    public void LessFoo()
    {
        DoSomethingElse();
    }
}

It needs to be "wired". I like attributes as you don't need to explicitly specify the interceptor at IoC container wiring. You just specify an attribute to watch out for:

[Intercept(typeof(Logger)]
public class FooService : IFooService { ... }

and wire it:

var builder = new ContainerBuilder();
builder.RegisterType<FooService>()
   .EnableClassInterceptors();

Then create your Logger interceptor in another file:

class Logger : IInterceptor
{
    public void Intercept(IInvocation invocation) // implements the IInterceptor interface
    {
        _loggerService.Log("calling " + invocation.Method.Name);
        invocation.Proceed();
        _loggerService.Log("finished " + invocation.Method.Name);
    }
}

As you can see, you can create timers, try-catch blocks, and much more. Database context and other disposable resources is an interesting one:

class Logger : IInterceptor
{
    public void Intercept(IInvocation invocation) // implements the IInterceptor interface
    {
        using (var someThing = new SomeResource())
        {
            invocation.Proceed();
        }
    }
}

Usually with such a resource you need to use someThing inside your method. That's a topic for another question! (see invocation.SetArgumentValue or invocation.TargetType.GetProperties() to communicate to the enclosing class. I'm not 100% comfortable with this, so some comments from others would be helpful)

Then, take a logging as an example:

void ManageFoo()
{
    // sorry for the messy code, what else can I do?!
    _logger("more foo please");
    _fooService.MoreFoo();
    _logger("less foo please");
    _fooService.LessFoo();
    _logger("enough foo");
}

The actual concern of the ManageFoo method is lost in all the mess of logging (add security and other concerns and you can end up with a big mess).

Now you can rewrite it like this:

void ManageFoo()
{
    _fooService.MoreFoo();
    _fooService.LessFoo();
}
0
On

Java has AOP with aspectJ and weaving (LTW load time with a proxy, and complile time CTW) C# (Castle) has intersceptors, that use a (dynamic) proxy as well. You can see it as the LTW variant.

I used this setup in c#. It is no big magic, and quite limited code.

Autofac 5.1.0
Autofac.Extras.DynamicProxy 5.0.0
Castle.Core 4.4.0

The trick is to

  1. define some attibute, that you use as intersceptor attribute
  2. define a intersceptor, that checks for the attribute on the method called
  3. define a interface with a method and the attribute on the interface method
  4. define implementation class of the interface
  5. register the whole setup with autofac
  6. test/run/go

1) define some attibute

using System;
[AttributeUsage(
AttributeTargets.Method,
AllowMultiple = true)]

public class SomeAttribute : Attribute
{
    public long Id { get; set; }
}

2) Define a Castle dynamic intersceptor (aka proxy)

using Castle.DynamicProxy;
using System;
public class SomeInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
         if (Attribute.IsDefined(invocation.Method, typeof(SomeAttribute)))
        {
            Console.Write("Method called: " + invocation.Method.Name);
        }
        invocation.Proceed();
    }
}

Now, create a object with a interface (dont forget, put the attribute on the interface, not on the impl!)

3) define a interface

public interface AOPTest
{
    [Some(Id = 10)]
    void DoSomething();
}

4) define implementation :

public class AOPTestImpl : AOPTest
{
    public void DoSomething()
    {
    }
}

5) register the whole setup with autofac

builder.RegisterType<AOPTestImpl>()
            .As<AOPTest>()
            .EnableInterfaceInterceptors()
            .InterceptedBy(typeof(SomeInterceptor));

builder.RegisterType<SomeInterceptor>().AsSelf();

6) test/run/go : run the whole setup:

using Autofac;
using Autofac.Extras.DynamicProxy;
using (var scope = bootstrap.BootStrap.Container.BeginLifetimeScope())
{
     var aOPTest = scope.Resolve<AOPTest>();
     aOPTest.DoSomething();
}

I dont know how it excactly works but the idea is:

interface -> proxy -> implementation So if you call the implementation over the interface, the proxy/intersceptor is in between.

Note: If you call other code inside the doSomething() method that needs intersception as well, you probably need a autofac class intersceptor EnableClassInterceptors

Note: it is not the fastest solution in the world. Probably some filtering intersceptor is faster, and compile time weaving like Fody or PostSharp are probably faster. But this will do a lot of times.

Note: if you need something done @Before start of the method, code it before the invocation.Proceed(); If you need something done at the end, code it if @After the invocation.Proceed() call:

@Before

DoSomething(){...}

@After