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

Introducing the KingAOP Framework: Part 1

4.91/5 (9 votes)
24 Jul 2013CPOL4 min read 44.9K   286  
KingAOP - It's an AOP framework which is essentially a free alternative of PostSharp.

Introduction

KingAOP - It's an AOP framework which is essentially a free alternative of PostSharp. If you are familiar with PostSharp, then you can notice that KingAOP has the similar interfaces. The main reason of creation of KingAOP was that currently we have several frameworks which provide a nice opportunities for AOP but no one has so simple and explicit interaction with developer as PostSharp. I like API of PostSharp because it's predictable and anyone can understand it from first glance. The second reason was, there are many questions on stackoverflow about free alternatives of PostSharp. It was pretty valuable argument to start development. The third reason was requirement to obtain the easy and transparent access to weaving code. Also I wanted to get rid of dependency in generating code in post compile phase via some third party IL generator. Instead of it I use the native C# compiler without shifting duties on some non official IL generator. On that moment I was really digging into "dynamic" C# and hence I realized that it's possible to get all AOP things which will based on "dynamic" + "DLR Trees"(for metaprogramming).

Background

This article assumes that you're familiar with the concept of AOP and PostSharp framework.

Using the code

In this article I going to show you the basic and simple concept of interception methods. Let's start our diving in AOP world via well known MethodInterceptionAspect<code><code> aspect. This aspect allows you to intercept invocation of method call and do anything what you want. For example you can put the additional validation, caching, logging, wait/retry, automatic thread delegation, lazy loading, invoke additional methods or just not invoke original method and so on. Actually this aspect replaces the method body with a call to the aspect, then moves the original body elsewhere.

Our test example will be: to invoke method and print passed arguments with values. I can agree it's not so useful requirement but it show you the basic concept. In next parts we will look on more useful examples.

So to try KingAOP power let's create simple PrintArgsAspect class inherited from MethodInterceptionAspect with overridden OnInvoke method. Basically it will be our test aspect for experiments. PrintArgsAspect will be responsible to print arguments values.

C#
class PrintArgsAspect : MethodInterceptionAspect
{
    public override void OnInvoke(MethodInterceptionArgs args)
    { }
}

The OnInvoke method will be invoked instead of real method and here is the place to do useful things. As you can see we acquire all arguments via MethodInterceptionArgs, this entry point allow us to make decision what we will do next: change arguments, throw exception, invoke original method, skip invocation of original method and so on. As long as we wanted just to take argument's value and print it, let's do that.

C#
class PrintArgsAspect : MethodInterceptionAspect
{
    public override void OnInvoke(MethodInterceptionArgs args)
    {
        // print arguments values
        string logData = PrintArgs("OnInvoke", args);
        Console.WriteLine(logData);
        
        // invoke original method
        args.Proceed();
    }

    string PrintArgs(string methodStage, MethodInterceptionArgs args)
    {
        var str = new StringBuilder();
        str.AppendLine();
        str.AppendLine(string.Format(methodStage + " {0} ", args.Method));

        foreach (var argument in args.Arguments)
        {
            var argType = argument.GetType();

            str.Append(argType.Name + ": ");

            if (argType == typeof(string) || argType.IsPrimitive)
            {
                str.Append(argument);
            }
            else
            {
                foreach (var property in argType.GetProperties())
                {
                    str.AppendFormat("{0} = {1}; ",
                        property.Name, property.GetValue(argument, null));
                }
            }
        }
        return str.ToString();
    }
}

Also please notice that to invoke original method we call Proceed method. Let's assume that we have TestRepository class with Save method where we want to apply our aspect.

C#
class TestRepository
{
    public void Save(TestEntity entity)
    { }
}

Also we have TestEntity class which is our argument of Save method of TestRepository class.

C#
class TestEntity
{
    public int Number { get; set; }
    public string Name { get; set; }
}

In order to apply some aspect of KingAOP we should inherit TestRepository from IDynamicMetaObjectProvider interface. It's necessary for DLR to invoke our aspect via dynamic. You can think about it as indicator for DLR to do dynamic magic. The IDynamicMetaObjectProvider require to implement GetMediaObject method. This method should always returns KingAOP's AspectWeaver object which will generate code of aspect.

C#
class TestRepository : IDynamicMetaObjectProvider
{
    [PrintArgsAspect] // apply aspect
    public void Save(TestEntity entity)
    { }

    // need for AOP weaving
    public DynamicMetaObject GetMetaObject(Expression parameter)
    {
        return new AspectWeaver(parameter, this);
    }
} 

The above implementation has method Save with applied PrintArgsAspect aspect and now if you invoke Save method like this testRepository.Save(entity); the PrintArgsAspect will intercept Save (original) method invocation and print arguments. It's time to show the demo, let's look on it.

C#
class Program
{
    static void Main(string[] args)
    {
        var entity = new TestEntity { Name = "Jon", Number = 99 };
        dynamic repository = new TestRepository();
        repository.Save(entity); // this method call will be intercepted by our aspect
    }
}

On console output we will have:

As you have noticed we printed argument values which passed to method Save and we used dynamic keyword. Without dynamic it doesn't work. Basically dynamic just tells C# compiler to generate necessary code for DLR to invoke our aspect.  

Points of Interest  

If you are curious about speed I would say that dynamic code blazingly fast. It's not a joke! After first invocation of method the DLR compiles all code to native IL and gets very optimized delegate which will be invoked in further calls. In other words you should think about dynamic as a normal C# code.

License

The entire KingAOP framework is licensed under the terms of the MIT license, meaning that you are free to use the library DLL in your commercial applications.

License

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