Thursday, August 2, 2012

Method interception in C# using Fluent AOP


FluentAOP is a lightweight, fluent interface based library that allows implementing aspects of method interception in a simpler and easier way. FluentAOP is primarily designed to simplify the adoption and use of AOP in .NET. In contrast to most AOP implementations, its interception semantics exclusively rely on strongly-typed method definitions and a fluent API.
Check this link for more details on method interception and AOP.
Creating the FluentAOP proxy is as easy as 
return new Proxy<IEmployeeService>().Target(new EmployeeService()).Save();

The OnBefore and OnAfter methods can be used to execute some logic before and after the intercepted method is invoked for execution.
[TestMethod]
public void OnBeforeExecutesTheActionBeforeTheMethodIsCalled()
{
    var service = EmployeeServiceFactory.Create();
    var employees = service.GetAll();
    Assert.IsTrue(employees.Any(e => e.Id == 10));
}

return new Proxy<IEmployeeService>()
    .Target(new EmployeeService())
    .InterceptMethod(m => m.GetAll())
    .OnBefore(m =>
                    {
                        var service = m.Target as IEmployeeService;
                        if(service == null) throw new TypeAccessException();
                        service.Add(new Employee(10, "Test Employee"));
                    })   
    .OnAfter(m => Debug.WriteLine(string.Format("Method called with argument {0}", m.Arguments[0])))
    .Save();

The OnInvoke method can be used to intercept the method call.

[TestMethod]
public void OnInvokeShouldInterceptTheActualMethodExecution()
{
    var service = EmployeeServiceFactory.Create();
    var employees = service.GetAll();
    Assert.IsTrue(employees != null);
}

return new Proxy<IEmployeeService>()
    .Target(new EmployeeService())
    .InterceptMethod(m => m.GetAll())   
    .OnInvoke((m) =>
                    {
                        if(Cache.Instance.Exists("Employees"))
                            return Cache.Instance.Get("Employees") as IEnumerable<Employee>;
                        return m.Method.Invoke(m.Target, m.Arguments);
                    } )
    .Save();
You can also use the OnReturn method to intercept the return value from the method and take actions based on the value.

[TestMethod]
public void OnReturnShouldBeCalledAfterTheInterceptedMethodExecutionCompletes()
{
    var service = EmployeeServiceFactory.Create();
    service.GetAll();
    Assert.IsTrue(Cache.Instance.Exists("Employees"));
}

return new Proxy<IEmployeeService>()
    .Target(new EmployeeService())
    .InterceptMethod(m => m.GetAll())
    .OnReturn((m, r) =>
                    {
                        Cache.Instance.Update("Employees", r);
                        return r;
                    })
    .Save();


2 comments:

DZONEMVB said...

I'm a community blog curator for DZone. I wanted to talk with you about potentially featuring your blog on DZone's .NET and node.js related content portals. sSnd me an email at mpron [at] dzone{dot} com and I'll explain the details.

DZONEMVB said...

I'm a community blog curator for DZone. I wanted to talk with you about potentially featuring your blog on DZone's .NET and node.js related content portals. send me an email at mpron [at] dzone{dot} com and I'll explain the details.