PostSharp – Ticklish Techs https://www.ticklishtechs.net a mostly .NET but also some other cool techs blog Thu, 13 Aug 2020 18:46:56 +0000 en-US hourly 1 https://wordpress.org/?v=5.7.11 First steps on aspect oriented programming https://www.ticklishtechs.net/2008/01/25/first-steps-on-aspect-oriented-programming/ Thu, 24 Jan 2008 23:43:55 +0000 http://www.ticklishtechs.net/2008/01/25/first-steps-on-aspect-oriented-programming/ Since I saw the first implementation of aspect oriented programming (AOP) frameworks for java I became a fan of AOP but it took a long time till now before I could start using AOP in my projects. The main reason was that simply no good and easy to use AOP framework for .net existed. There was one research project but you weren’t allowed to use their utilities in project other then research projects.
But a few weeks ago I discovered PostSharp and it is really great and very simple. If you have no idea what’s all about AOP you should read the Wikipedia article or the start page of the PostSharp project. There you find a short example showing the usage of an aspect in C# code.
I also want to show you my first experience with some aspect oriented programming.

First: the problem I want to address
I sounds very simple: I’ve got a base-class and some sub-classes. All provide a method GetName(). All sub-classes within the same type should return the same name that is given at compile time. It’s just a const string for each class. The following code addresses these needs in a straight forward way:

class BaseClass

{

    public virtual string GetName()

    {

        return “-“;

    }

}

 

class ClassA : BaseClass

{

    public override string GetName()

    {

        return “A”;

    }

}

 

class ClassB : BaseClass

{

    public override string GetName()

    {

        return “b”;

    }

}

Second: what I don’t like with this solution
This seems good, but I’ve got some more special needs. All classes are generated by the DSL Tools that means they contain much other code and no line written by me. In my use case these classes are shape-objects.
Thanks to the partial keyword in C# I could extend every class within its own .cs-file, but I didn’t like this. It would mean I have to create many additional .cs-files only for providing a single string to the class. But all other definition is stored in the DSL-model described by the DSL Tools and some part of the shape declaration is located in the .cs-files.
In the DSL-model I can provide each class with a custom attribute, so I’m looking for a solution with no additional code in the sub-classes besides a custom attribute.
With the use of reflection it could be the following:

class NameTextAttribute : Attribute

{

    public NameTextAttribute(string name)

    {

        this.Name = name;

    }

 

    public string Name { get; set; }

}

 

class BaseClass

{

    private string name = null;

 

    public virtual string GetName()

    {

        if (name == null)

        {

            object[] a = this.GetType().GetCustomAttributes(

                            typeof(NameTextAttribute),

                            true);

 

            if (a.Length > 0)

                name = ((NameTextAttribute)a[0]).Name;

            else

                name = “-“;

        }

 

        return name;

    }

}

 

[NameTextAttribute(“A”)]

class ClassA : BaseClass {}

 

[NameTextAttribute(“b”)]

class ClassB : BaseClass {}

This is working and as you see, no additional code is needed in the sub-classes. But nevertheless I would like to avoid using reflection. Reflection seems to me inappropriate in this case.

Third: Using AOP
The idea of AOP is to add code to the class that you can write in another position, in the aspect. The aspect weaver (in my case the PostSharp Laos library) adds this code on compiletime (not runtime!) to the class.
My strategy is to add some code after the constructor execution that will initialize the name-property:

class BaseClass

{

    public virtual string Name { get; internal set; }

 

    public virtual string GetName()

    {

        return this.Name;

    }

}

 

[NameAspect(“a”)]

class ClassA : BaseClass

{

    public void someMethodInA()   { }

}

 

[NameAspect(“b”)]

class ClassB : BaseClass {}

 

[Serializable]

class NameAspect : OnMethodBoundaryAspect

{

    private string name = “-“;

    public NameAspect(string name)

    {

        this.name = name;

    }

 

    override bool CompileTimeValidate(MethodBase m)

    {

        return m.IsConstructor;

    }

 

    override void OnSuccess(MethodExecutionEventArgs args)

    {

        BaseClass obj = args.Instance as BaseClass;

        if (obj != null)

            obj.Name = name;

    }

}

The base-class now provides a property name (declared with the new C# 3.0 syntax) and the GetName() method returning the property value. As in the last example the sub-classes have the attribute declared and contain no other code.
The magic happens in the attribute (or, if you like, somewhere in the PostSharp.dll). It is derived from OnMethodBoundaryAspect, an aspect base type where I can add code to a method in another class before and after the method call and on exception and on success of the method call.
My constructor of this aspect gets only the name string and stores it in a variable.
The code that should be executed every time a constructor of a class with this aspect is calls can be find in the OnSuccess()-method. Here only the property of the BaseClass will be set.
With the CompileTimeValidate()-method I can specify at compiletime for witch methods the code should be injected. For my needs this is only the constructor. All other methods of my class will not be changes by this aspect.

Fourth: behind the scene
With adding the PostSharp references to my project the PostSharp postcompiler is called automatically after compiling my assembly and the code is added. If you take a look with the Reflector you will see the following:

class ClassA : BaseClass

{

    static ClassA()

    {

        if (!~PostSharp~Laos~Implementation.initialized)

            LaosNotInitializedException.Throw();

        ~PostSharp~Laos~Implementation.~targetMethod~3 =

                methodof(ClassA..ctor);

        ~PostSharp~Laos~Implementation.NameAspect~3.RuntimeInitialize

                (~PostSharp~Laos~Implementation.~targetMethod~3);

    }

 

    public ClassA()

    {

        MethodExecutionEventArgs ~laosEventArgs~1;

        try

        {

            ~laosEventArgs~1 = new MethodExecutionEventArgs(

                    methodof(ClassA..ctor, ClassA), this, null);

            ~PostSharp~Laos~Implementation.NameAspect~3.OnEntry(~laosEventArgs~1);

            if (~laosEventArgs~1.FlowBehavior != FlowBehavior.Return)

                ~PostSharp~Laos~Implementation.NameAspect~3.OnSuccess(~laosEventArgs~1);

        }

        catch (Exception ~exception~0)

        {

            ~laosEventArgs~1.Exception = ~exception~0;

            ~PostSharp~Laos~Implementation.NameAspect~3.OnException(~laosEventArgs~1);

            switch (~laosEventArgs~1.FlowBehavior)

            {

                case FlowBehavior.Continue:

                case FlowBehavior.Return:

                    return;

            }

            throw;

        }

        finally

        {

            ~PostSharp~Laos~Implementation.NameAspect~3.OnExit(~laosEventArgs~1);

        }

    }

 

    public void someMethodInA() {}

}

I really don’t know what’s that all about but I can see that there is code added only to the constructor, someMethed() is empty as in my given source code.

In the next weeks I will try to cover more examples and solutions with PostSharp and AOP.

]]>