Click here to Skip to main content
15,884,629 members
Articles / DevOps / Load Testing

Aspect Oriented Programming: learn step by step and roll your own implementation!

Rate me:
Please Sign up or sign in to vote.
4.98/5 (129 votes)
11 Sep 2013CPOL21 min read 242.7K   2K   240  
A journey into AOP land with concerns, pointcuts, joinpoints, advices, aspects, interceptors, proxies, targets, mix-ins, composites...
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--------------------------------------------------------------------------->
<!--                           INTRODUCTION                                

 The Code Project article submission template (HTML version)

Using this template will help us post your article sooner. To use, just 
follow the 3 easy steps below:
 
     1. Fill in the article description details
     2. Add links to your images and downloads
     3. Include the main article text

That's all there is to it! All formatting will be done by our submission
scripts and style sheets. 

-->
<!--------------------------------------------------------------------------->
<!--                        IGNORE THIS SECTION                            -->
<html>
<head>
    <title>The Code Project</title>
    <style>
        BODY, P, TD
        {
            font-family: Verdana, Arial, Helvetica, sans-serif;
            font-size: 10pt;
        }
        H2, H3, H4, H5
        {
            color: #ff9900;
            font-weight: bold;
        }
        H2
        {
            font-size: 13pt;
        }
        H3
        {
            font-size: 12pt;
        }
        H4
        {
            font-size: 10pt;
            color: black;
        }
        PRE
        {
            background-color: #FBEDBB;
            font-family: "Courier New" , Courier, mono;
            white-space: pre;
        }
        CODE
        {
            color: #990000;
            font-family: "Courier New" , Courier, mono;
        }
    </style>
    <link rel="stylesheet" type="text/css" href="http://www.codeproject.com/App_Themes/Std/CodeProject.css">
</head>
<body bgcolor="#FFFFFF" color="#000000">
    <!--  Fill in the details (CodeProject will reformat this section for you) -->
    <pre>
Author:      Guirec Le Bars
Email:       glebars20@hotmail.com
</pre>
    <h1>
        Aspect Oriented Programming: learn step by step and roll your own implementation!</h1>
    <p>
        A journey into AOP land with concerns, pointcuts, joinpoints, advices, aspects,
        interceptors, proxies, targets, mix-ins, composites...</p>
    <h2>
        Introduction</h2>
    <p>
        AOP stands for Aspect Oriented Programming. I guess every reader is familiar with
        the OP part of the acronym so we will have to clarify what Aspect means and don’t
        worry we’ll come to that later in the article.</p>
    <p>
        I’ll (try to) keep this article at beginner level. Knowledge of Object Oriented
        Programming concepts is the only requirement to read further!</p>
    <p>
        In my opinion understanding properly a concept make you a better consumer of its
        implementation. But, I do understand that the article is a bit long so if you feel
        bored or discouraged I still encourage you to jump to the implementation part. You'll
        still be able to come back to theory later.
    </p>
    <h2>
        Advanced developers, read this!</h2>
    <p>
        If you are familiar with AOP then don't leave yet!<br />
        Let me already disclose straight away what this article has to offer...
    </p>
    <p>
        I will introduce an <strong>interception technique </strong>which can (and do actually
        :-) ):
    </p>
    <ul>
        <li>Intercept <b>any class</b> (including sealed, static, value types)</li>
        <li>Intercept <b>constructors</b></li>
        <li>Intercept <strong>type initializers</strong></li>
        <li>Intercept instance <strong>methods, properties and eventsand events</strong> (even
            if they are not marked as virtual)</li>
        <li>Intercept <b>static</b> methods, properties and events</li>
    </ul>
    <p>
        Without</p>
    <ul>
        <li>Weaving your code or your assemblies</li>
        <li>emitting IL code</li>
        <li>using any dynamic stuff</li>
        <li>modifying your target class</li>
        <li>forcing the weavers to implement anything (such as MarshalByRef)</li>
    </ul>
    <p>
        Basically we are talking about a pure managed code technique which could run on
        .Net 1.1 (actually I use bits of Linq but you can change t that easily) and which
        allows you to intercept almost anything you might think of.
    </p>
    <p>
        Let&#39;s be more clear. With the following technique:</p>
    <p>
        you can intercept stuff such as <code>System.DateTime.Now</code> or <code>System.IO.File</code>
        operations!
        <br />
        you don&#39;t have the usual limitations of the most popular interceptions library.</p>
    <p>
        Are you guys doubting ? then read further!!
    </p>
    <h2>
        Background</h2>
    <p>
        Some might think they have not made their full journey into Object Oriented Programming
        so why would they switch from OOP to AOP and abandoned all the concepts they hardly
        have learnt over the years? Answer is simple: there is no switch. <b>There is no: OOP
            vs AOP!</b> AOP is one of these concepts which name, in my opinion, is misleading.
        Embracing the AOP principles lets you dealing with classes, objects, interfaces,
        inheritance, polymorphism, abstraction etc… so there is no way you get lost as you
        are still fully immersed in the OOP world.</p>
    <p>
        When applying AOP concepts in your code you are attempting to relax one particular,
        and not the least, principle of OOP which is encapsulation to adress cross-cutting
        concerns (we'll come back to that later on).
    </p>
    <p>
        Back in the old days, when internet was only yellow pages, bulleting boards and
        usenet, you were better to read books if you wanted to learn anything (comment for
        the y generation : a book is a thing with written sheets of paper stuffed in it).
        And all these books would approximately remind you this regarding the OOP subject:</p>
    <ul>
        <li>Rule #1: you have to encapsulate all you data and code</li>
        <li>Rule #2: never ever break Rule #1</li>
    </ul>
    <p>
        <strong>Encapsulation</strong> has been the ultimate goal for introducing OOP concepts
        in 3<sup>rd</sup> generation languages (<a href="http://en.wikipedia.org/wiki/Third-generation_programming_language">3GL</a>).
    </p>
    <cite><u>Wikipedia:</u><br />
        <b>Encapsulation</b>&nbsp;is used to refer to one of two related but distinct notions,
        and sometimes to their combination: </cite>
    <ul>
        <li><cite>A language mechanism for restricting access to some of the object’s components.</cite></li>
        <li><cite>A language construct that facilitates the bundling of data with the methods
            (or other functions) operating on that data.</cite></li>
    </ul>
    <p>
        AOP, in a way, is claiming that it, <u>sometimes</u>, should be possible to use:
        <br />
        <b>a language construct that facilitates the bundling of methods (or other functions)
            operating with encapsulated data without the data.</b>
    </p>
    <p>
        Got that? Then you get all that is to know about the theory. Good job!</p>
    <p>
        Now we are naturally leaded to the 2 following questions:
    </p>
    <ul>
        <li>When is “sometimes”?</li>
        <li>Why should it be possible? </li>
    </ul>
    <h2>
        On usefulness of AOP... some scenarii</h2>
    <p>
        Let&#39;s take a look at a the following situations:</p>
    <h3>
        Scenario A</h3>
    <p>
        You are software developer in a bank. The bank has a pretty working operational
        system. The business is running smoothly. Government emits a policy which enforces
        banks to commit on some sort of transparency. Whenever money goes in or out of the
        bank it should be logged. The government publicly said that this is a first measure
        towards transparency but that more is to be expected.
    </p>
    <h3>
        Scenario B</h3>
    <p>
        Your web application has been released to test team. All functional tests passed
        but the application failed at load testing. A non-functional requirement stated
        that no page should take more than 500 ms to process on the server. After analysis
        there are dozens of queries made to the database that could be avoided by caching
        the results.</p>
    <h3>
        Scenario c</h3>
    <p>
        You have spent the last 2 years modeling your domain model in a perfect library
        consisting of 200+ classes. Lately you’ve been told that a new application front-end
        will be written and this guy needs to bind your objects to the UI. But to facilitate
        that task all your classes should now implement <code>INotifyPropertyChanged</code>.</p>
    <p>
        These examples are valid in terms of the why and when AOP could come to the rescue.
        These scenarii have the following in common:</p>
    <h3>
        Cross-cutting concerns</h3>
    <p>
        <u>When is "sometimes”?</u></p>
    <p>
        Some classes (Bank class, Data access services, Domain model classes, etc…) designed
        to achieve a given functionality have to be modified to handle a requirement which
        is basically “not their own business”.</p>
    <ol>
        <li>The Bank class purpose is money exchange. The logging concern is Government’s interest.</li>
        <li>The Data Services classes purpose is to retrieve data. The data caching concern
            is a non-functional requirement.</li>
        <li>The domain model classes purpose is to handle your company’s business. The concern
            about notification of property changed is in the UI interest.</li>
    </ol>
    <p>
        It is whenever you have to write some code over different classes to fulfill an
        interest external to these classes. In AOP dialect it is whenever you have a <strong>
            cross-cutting concern</strong>.</p>
    <p>
        The notion of <strong>cross-cutting concern</strong> is centric to AOP. <b>No cross-cutting
            concern = no need for AOP!</b></p>
    <p>
        <u>why should it be possible?</u></p>
    <p>
        Let’s take a closer look at Scenario C.<br />
        Your problem is that you have an average of 5 properties exposed by each class in
        your domain model. With 200+ classes you will have to implement (copy/paste) more
        than 1,000 times some boiler plate code to transform something which looks like
        this:</p>
    <pre lang="C#">
public class Customer
{
    public string Name { get; set; }
}
</pre>
    <p>
        Into something like that:</p>
    <pre lang="C#">
public class Customer : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
        
    private string _Name;
    public string Name 
    { 
        get { return _Name; }
        set
        {
            if (value != _Name)
            {
                _Name = value;
                SignalPropertyChanged("Name");
            }
        }
    }

    void SignalPropertyChanged(string propertyName)
    {
        var pcEvent = this.PropertyChanged;
        if (pcEvent != null) pcEvent(this, new PropertyChangedEventArgs(propertyName));
    }
}
</pre>
    <p>
        Uh! And that is for one property only! BTW, did you know the intern left 2 days
        ago? :-)</p>
    <p>
        I think you get the why without further explanation...</p>
    <p>
        It should be possible <i>"to bundle the methods operating with encapsulated data without
            the data"</i> in other words : externalise the implementation of the cross-cutting
        <code>INotifyPropertyChanged</code> concern with no or minimum impact on domain
        model classes like <code>Customer</code>.</p>
    <p>
        If we can achieve that then we will:</p>
    <ol>
        <li>Have a proper separation of concerns</li>
        <li>Avoid code repetition and thus facilitate code maintenance </li>
        <li>Avoid hiding domain classes core business under tons of boiler plate code</li>
    </ol>
    <p>
        Yeahh... ok, that's all nice and fancy and stuff but <b>how can we do?</b></p>
    <h3>
        The theorical answer</h3>
    <p>
        We have a <b>cross-cutting concern</b> which requires some code to be executed in
        several classes (<strong>targets</strong> from now on).<br />
        The implementation (the code which implements Logging, or Cache, or whatever) is
        simply called <b>concern</b> in the AOP world.
    </p>
    <p>
        We should then be able to attach (inject, introduce, etc... choose your word) our
        <b>concern</b> (I repeat because it is important: <u>the <b>concern</b> is the implementation</u>
        for your <b>cross-cutting concern</b>) at any chosen place of the <strong>target</strong>.<br />
        And we should be able to choose any of the following places of the <strong>target</strong>
        to attach our <strong>concern</strong>:</p>
    <ul>
        <li>Static initializers</li>
        <li>Constructors</li>
        <li>Static Property getters and setters</li>
        <li>Instance Property getters and setters</li>
        <li>Static methods</li>
        <li>Instance Methods</li>
        <li>Destructors</li>
    </ul>
    <p>
        In a perfect AOP world we should be able to attach our <strong>concern</strong>
        at any line of code of the <strong>target</strong>.</p>
    <p>
        Fine, but if we want to attach a <b>concern</b> we need a hook in the <strong>target</strong>,
        don’t we? Yes captain!<br />
        In AOP the notion of that hook (the place where your <strong>concern</strong> is
        going to be attached for execution) has a name: it is a <b>pointcut</b>. And the
        place from where you actualy attach the code has also a name : it is a <b>joinpoint</b>.</p>
    <p>
        Clear enough? Maybe not.... Here is some pseudo-code that hopefully demonstate the
        idea:</p>
    <pre>

// Target class
class BankAccount
{
    public string AccountNumber {get;}
    public int Balance {get; set;}
    void Withdraw(int AmountToWithdraw)
    {
        <b>:public pointcut1;</b>   // a pointcut (imagine something like a label for goto statement in BASIC or T-SQL etc...)
        Balance -= AmountToWithdraw;
    }
}

// Concern 
<b>concern</b> LoggingConcern
{
    void LogWithdraw(int AmountToWithdraw)
    { 
        // Here you have to imagine that some kind of 'magic' has happened
        // and 'this' is an instance of the BankAccount class.
        Console.WriteLine(<b>this.AccountNumber</b> + " withdrawal on-going...");
    }
}

class Program
{
    void Main()
    {
        // get a reference to the pointcut marker  through reflection
        pointcut = typeof(Bank).GetPointcut("<b>pointcut1</b>");

        // this is the joinpoint 
        <b>LoggingConcern.Join(cutpoint, LogWithdraw); </b>

        // After joinpoint the runtime should have (in a sort of registry)
        // a record which tells to execute our LoggingConcern at pointcut1 of Bank class
    }
}
</pre>
    <p>
        Would'nt it be great to have such mechanism available out of the C# box???
    </p>
    <h3>
        A few more definitions</h3>
    <p>
        Before we move on to our actual implementation let's introduce a few more definitions...</p>
    <p>
        <u>What is an <b>Aspect</b>?</u><br />
        It is the association of a <b>concern</b>, a <b>point cut</b> and a <b>joinpoint</b>.<br />
        Think of it for a second and I hope it will be crystal clear: the fact that I have
        a Logging mechanism (<b>concern</b>), that I register its log method to be executed
        (<b>joinpoint</b>) at a given place of my application code (<b>pointcut</b>) is
        one <b>aspect</b> of my application.
    </p>
    <p>
        But wait a minute... What could/should a <b>concern</b> be allowed to do once injected?</p>
    <p>
        <b>Concerns</b> are categorized into 2 categories:</p>
    <ul>
        <li><u><b>Side effects</b>:</u><br />
            A <b>side effect</b> is a <b>concern</b> which is not changing the behavior of the
            code at <b>pointcut</b>. A <b>side effect</b> just introduce an additional action
            to perform.<br />
            A Logging <b>concern</b> is a good example of a <b>side effect</b>: whenever the
            runtime execute the targeted method (eg:<code>Bank.Withdraw(int Amount)</code>)
            the <code>LoggingConcern.LogWithdraw(int Amount)</code> method will be executed
            and the <code>Bank.Withdraw(int Amount)</code> method will continue execution.<br />
            <br />
        </li>
        <li><u><b>Advices</b>:</u><br />
            An <b>advice</b> is a <b>concern</b> which might change the input/output of the
            method.<br />
            A Caching <b>concern</b> is a perfect example: Whenever the runtime execute the
            targeted method (eg: <code>CustomerService.GetById(int Id)</code>) the <code>CachingConcern.TryGetCustomerById(int
                Id)</code> will be executed and will force the <code>CustomerService.GetById(int Id)</code>
            method to return with the value found in cache, if any, otherwise will let the execution
            continue.<br />
            <br />
            <b>Advices</b> should be allowed to:<br />
            <ul>
                <li>Inspect the input parameters at targeted pointcut and modify them if needed</li>
                <li>Cancel the execution of the targeted method and replace it with a different implementation</li>
                <li>Inspect the output result od the targeted method and modify or replace it</li>
            </ul>
        </li>
    </ul>
    <p>
        At that point if you are still reading then congratulations! Bravo! Parce que vous
        le valez bien ;-)
    </p>
    <p>
        We are done with the general concepts and ideas of AOP. Let's move forward and see
        how we can get close to that with C#...</p>
    <h2>
        Show me some code ou je tue le chien!</h2>
    <h3>
        <b>Concerns</b></h3>
    <p>
        The <b>concern</b> should have a magic <code>this</code> behavior which is of our
        <strong>target</strong> type.<br />
        That's no problemo!
    </p>
    <pre lang="C#">
public interface IConcern&lt;T&gt;
{
    T This { get; } // ok, that's a bit of cheating but who cares?
}   </pre>
    <h3>
        <b>Reference to pointcuts</b></h3>
    <p>
        There is no easy way to get <b>pointcuts</b> for every single line of code. But
        we can get one at each method call and that's fairly easy by using the <a href="http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.aspx">
            <code>System.Reflection.MethodBase</code></a> class. MSDN is not really verbose
        about it: <cite>Provides information about methods and constructors.</cite>[sic].
    </p>
    <p>
        Between you and me using <code>MethodBase</code> for getting reference to <b>pointcuts</b>
        is the most powerful possibility at your disposition.
    </p>
    <p>
        You can get reference to pointcuts for Constructors, Methods, Properties and Events
        as for .Net almost anything you declare in your code (apart from fields) ends up
        being a method...<br />
        See yourselves:
    </p>
    <pre lang="C#">
public class Customer 
{
    public event EventHandler&lt;EventArgs&gt; NameChanged;
    public string Name { get; private set; }
        
    public void ChangeName(string newName) 
    {
        Name = newName;
        NameChanged(this, EventArgs.Empty);
    }
}

class Program
{
    static void Main(string[] args)
    {
        var t = typeof(Customer);

        // Constructor (not limited to parameterless)
        var pointcut1 = t.GetConstructor(new Type[] { });

        // The ChangeName method
        var pointcut2 = t.GetMethod("ChangeName");

        // the Name property
        var nameProperty = t.GetProperty("Name");
        var pointcut3 = nameProperty.GetGetMethod();
        var pointcut4 = nameProperty.GetSetMethod();

        // Everything about the NameChanged event
        var NameChangedEvent = t.GetEvent("NameChanged");
        var pointcut5 = NameChangedEvent.GetRaiseMethod();
        var pointcut6 = NameChangedEvent.GetAddMethod();
        var pointcut7 = NameChangedEvent.GetRemoveMethod();
    }
}
</pre>
    <h3>
        <b>Joinpoints</b></h3>
    <p>
        Writing the code for joining is fairly easy as well. Look at the signature of the
        method below :<br />
    </p>
    <code>void Join(System.Reflection.MethodBase pointcutMethod, System.Reflection.MethodBase
        concernMethod);</code>
    <p>
        We can add that signature to a sort of registry that we will provide later on and
        we can already imagine writing code like this one!!!</p>
    <pre lang="C#">
public class Customer
{
    public string Name { get; set;}
    public void DoYourOwnBusiness() 
    {
        System.Diagnostics.Trace.WriteLine(Name + " is doing is own business");
    }
}

public class LoggingConcern : IConcern&lt;Customer&gt;
{
    public Customer This { get; set; }

    public void DoSomething() 
    {
        System.Diagnostics.Trace.WriteLine(This.Name + " is going to do is own business");

        This.DoYourOwnBusiness();
            
        System.Diagnostics.Trace.WriteLine(This.Name + " has finished doing its own business");
    }
}

class Program
{
    static void Main(string[] args)h
    {
        // Get a pointcut for Customer.DoSomething();
        var pointcut1 = typeof(Customer).GetMethod("DoSomething");
        var concernMethod = typeof(LoggingConcern).GetMethod("DoSomething");

        // Join them
        AOP.Registry.Join(pointcut1, concernMethod);
    }
}</pre>
    <p>
        How far are we from our pseudo-code? Personally I would say not much...<br />
        What's next then?</p>
    <h2>
        Glueing everything together...</h2>
    <p>
        That's where problems and fun start at the same time!
    </p>
    <p>
        But let&#39;s start simple with
    </p>
    <h3>
        The registry</h3>
    <p>
        The registry will keep records about <b>joinpoints</b>. It's a singleton list of
        joinpoint items.<br />
        A <b>joinpoint</b> is a simple struct :
    </p>
    <pre lang="C#">
public struct Joinpoint
{
    internal MethodBase PointcutMethod;
    internal MethodBase ConcernMethod;
    
    private Joinpoint(MethodBase pointcutMethod, MethodBase concernMethod)
    {
        PointcutMethod = pointcutMethod;
        ConcernMethod = concernMethod;
    }

    // Utility method to create joinpoints 
    public static Joinpoint Create(MethodBase pointcutMethod, MethodBase concernMethod)
    {
        return new Joinpoint (pointcutMethod, concernMethod);
    }
}
        </pre>
    <p>
        Nothing fancy... It should as well implement <code>IEquatable&lt;Joinpoint&gt;</code>
        but for making the code shorter here I have intentionally removed it</p>
    <p>
        And the registry: The class is called <code>AOP</code> and implements the singleton
        pattern. It exposes its unique instance through a public static property named <code>
            Registry</code></p>
    <pre lang="C#">
public class AOP : List&lt;Joinpoint&gt;
{
    static readonly AOP _registry;
    static AOP() { _registry = new AOP(); }
    private AOP() { }
    public static AOP Registry { get { return _registry; } }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void Join(MethodBase pointcutMethod, MethodBase concernMethod)
    {
        var joinPoint = Joinpoint.Create(pointcutMethod, concernMethod);
        if (!this.Contains(joinPoint)) this.Add(joinPoint);
    }
}
</pre>
    <p>
        With the <code>AOP </code>class we can now write construct like :
    </p>
    <pre lang="C#">AOP.Registry.Join(pointcut, concernMethod);</pre>
    <h3>
        Houston, we've got a problem</h3>
    <p>
        We've got an obvious and serious problem now to cope with. If a developer writes
        code like...</p>
    <pre lang="C#">
var customer = new Customer {Name="test"};
customer.DoYourOwnBusiness();
</pre>
    <p>
        ... there is just no reason why our registry would be consulted, so there is no
        way that our <code>LoggingConcern.DoSomething()</code> method is executed...</p>
    <p>
        Our problem is that .Net does not provide us with a simple way to intercept such
        calls out of the box.</p>
    <p>
        As there is no native way then some <u>work around</u> must be implemented. The
        capabilities of your work around is going to drive the capabilities of your AOP
        implementation.<br />
        The goal of this aricle is not to discuss all possible interception techniques but
        take note that <b>the interception model is the key differentiator</b> between all
        AOP implementations.<br />
        The SharpCrafters website (owners of PostSharp) is providing some clear information
        on the 2 major techniques:
    </p>
    <ul>
        <li><a href="http://www.sharpcrafters.com/aop.net/compiletime-weaving">Compile-time
            weaving</a></li>
        <li><a href="http://www.sharpcrafters.com/aop.net/runtime-weaving">Run-time weaving</a></li>
    </ul>
    <h3>
        Our interception technique: <a href="http://en.wikipedia.org/wiki/Proxy_pattern">Proxying</a></h3>
    <p>
        There is not much of a secret if you want to intercept all calls made to a class
        you have 3 choices:</p>
    <ol>
        <li>Create your own language and compiler to produce .net assemblies: when compiling
            you can inject whatever you want everywhere you want.</li>
        <li>Implement a solution which modifies the runtime behavior of assemblies</li>
        <li>Give a proxy to your consumer and intercept calls using an Interceptor class while
            marshaling the real subject (<strong>target</strong>)</li>
    </ol>
    <p style="font-size: 10px; padding-left: 40px;">
        <i>For advanced guys: I voluntarily don&#39;t mention Debugger API and Profiler API
            possibilities which are not viable for production scenarii.<br />
            For very advanced one: An hybrid of solutions 1 and 2 using the Roslyn API should
            be feasible and, as far as I know, it is still to be invented. A bon entendeur...</i></p>
    <p>
        Apart if you need to provide <b>pointcuts</b> at any single line of code then it
        seems that the 2 first solutions are a bit of over-engineering.<br />
        We'll go for the 3rd solution. Take note that usage of proxying technique comes
        with a good and a bad news:
    </p>
    <p>
        <u>The bad news</u> is that your <b>target</b> object must be swapped at runtime
        with a proxy object instance. Implying that if you want to intercept things such
        as constructors you'll have to delegate construction of your <b>target</b> class
        instances to a factory (that&#39;s a <b>cross-cutting concern</b> that this implementation
        won't solve :-(). If you already have an instance of the <strong>target</strong>
        class then you will have to explicitely <i>ask</i> for the swap to happen. For the
        IOC and Dependency Injection ninjas the delegation of objects creation will be less
        than an issue. For others it means they'll have to use a factory if they want to
        use our interception technique at its full extent. But don&#39;t worry we are going
        to implement that factory.</p>
    <p>
        <u>The good news</u> is that we have nothing to do to implement a proxy. The class
        <code>System.Runtime.Remoting.Proxies.RealProxy</code> will build it for us in a
        highly optimized way.</p>
    <p>
        In my opinion the class name does not reflect its use. This class is not a Proxy
        it is an Interceptor. But anyway that class will provide us with a Proxy by calling
        its method <code>GetTransparentProxy()</code> and that's the only thing we need.</p>
    <p>
        So the skeleton for our interceptor is :</p>
    <pre lang="C#">
public class Interceptor : RealProxy, IRemotingTypeInfo
{
    object theTarget { get; set; }

    public Interceptor(object target) : base(typeof(MarshalByRefObject))
    {
        theTarget = target;
    }

    public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg)
    {
        IMethodCallMessage methodMessage = (IMethodCallMessage) msg;
        MethodBase method = methodMessage.MethodBase;
        object[] arguments = methodMessage.Args;

        object returnValue = null;

        // TODO:
        // here goes the implementation details for method swapping in case the AOP.Registry 
        // has an existing joinpoint for the MethodBase which is hold in the "method" variable...
        // if the Registry has no joinpoint then simply search for the corresponding method 
        // on the &quot;theTarget&quot; object and simply invoke it... ;-)

        return new ReturnMessage(returnValue, methodMessage.Args, methodMessage.ArgCount, methodMessage.LogicalCallContext, methodMessage);
    }

    #region IRemotingTypeInfo
    public string TypeName { get; set; }
    public bool CanCastTo(Type fromType, object o) { return true; }
    #endregion
}
    </pre>
    <p>
        Some explanations are required here as we are now touching the heart of the implementation....
    </p>
    <p>
        The <code>RealProxy</code> class exists to serve the purpose of intercepting calls
        from remote objects and marshal a targeted object. By remote here you must understand
        really remote like : objects living in another application, another AppDomain, another
        server, etc...). I am not going to go too much in details but there were 2 ways
        to marshal objects in the .net Remoting infrastructure : by reference or by value.
        Basically it means you can only marshal remote objects if they are inheriting <code>
            MarshalByRef</code> or if they implement <code>ISerializable</code>. Our plan
        is not to use the remoting capabilities at all but we still need to let the <code>RealProxy</code>
        class think our target is acceptable for remoting. That's why we pass <code>typeof(MarshalByRef)</code>
        to the <code>RealProxy</code> base constructor.
    </p>
    <p>
        The <code>RealProxy</code> class is receiving all calls made on the transparent
        proxy via the <code>System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage
            msg)</code> method. That's where we will implement the details about method
        swapping. Read the comments in the code above.
    </p>
    <p>
        About the implementation of <code>IRemotingTypeInfo</code>: In a true remoting environment
        the client side would request an object to the server. The client application runtime
        might not know anything about the type of the marshalled remote object. So when
        the client app makes a call to the method <code>public object GetTransparentProxy()</code>
        the runtime must decide if the returned object (the transparent proxy) is boxable
        to the client application expected contract. By implementing <code>IRemotingTypeInfo</code>
        you give a hint to the client runtime telling if casting to a specified type is
        allowed or not.<br />
        And guess what the trick is there, in front of your astonished gaze, right here...
    </p>
    <pre lang="C#">
public bool CanCastTo(Type fromType, object o) { <strong>return true;</strong> }    </pre>
    <p>
        All our AOP implementation is only possible due to the possibility offered by remoting
        to write these 2 words: <code>return true;</code> <u>Passed that point we can cast the
            object returned by</u> <code>GetTransparentProxy()</code> <u>to whatever interface <b>
                without any runtime check!!!</b></u>.
    </p>
    <p>
        The runtime just purely and simply gave us a "yes card" to play with!</p>
    <p>
        We might want to revisit that code to return something more appropriate than true
        to any type... But we could also imagine make use of this behaviour to provide a
        <a href="http://haacked.com/archive/2009/08/25/method-missing-csharp-4.aspx">Missing
            Method</a> implementation or a catch all interface... There is a lot of room
        fot your creativity to express istself here!</p>
    <p>
        At that point we have a decent interception mechanism for our target instance. We
        are still mising interception of constructors and creation of the transparent proxy.
        That's a job for a factory...
    </p>
    <h3>
        The Factory</h3>
    <p>
        Not much to say about that one. Here is the skeleton of the class.</p>
    <pre lang="C#">
public static class Factory
{
    public static object Create&lt;T&gt;(params object[] constructorArgs)
    {
        T target;

        // TODO:
        // Base on typeof(T) and the list of constructorArgs (count and their Type)
        // we can ask our Registry if it has a constructor method joinpoint and invoke it
        // if the Registry has no constructor joinpoint then simply search for the corresponding one 
        // on typeof(T) and invoke it...
            

        // Assign the result of construction to the "target" variable
        // and pass it to the GetProxy method.
        return GetProxyFor&lt;T&gt;(target);
    }

    public static object GetProxyFor&lt;T&gt;(object target = null)
    {
        // Here we are asked to intercept calls on an existing object instance (Maybe we constructed it but not necessarily)
        // Simply create the interceptor and return the transparent proxy
        return new Interceptor(target).GetTransparentProxy();
    }
}
        </pre>
    <p>
        Note that the <code>Factory</code> class is always returning an object of type <code>
            object</code>. We can't return an object of type <code>T</code> because the
        transparent proxy is simply not of type <code>T</code>, it is of type <code>System.Runtime.Remoting.Proxies.__TransparentProxy</code>.
        But, remember the "Yes card", <b>we can cast the returned object to whatever interface
            without any runtime checking!</b></p>
    <p>
        We will nest the <code>Factory</code> class in the <code>AOP</code> class hoping
        to give a neat programming experience to our consumers. But you'll see that in the
        Usage section below</p>
    <h2>
        Final notes on implementation</h2>
    <p>
        If you have read the whole article till that point I must recognize you are almost
        a hero! Bravissimo! Kudos!
        <br />
    </p>
    <p>
        For the sake of brevity and clarity of this article (damned... why are you smiling?)
        I am not going to discuss the boring implementation details of method retrievals
        and switching. There is actually not much fun in it. But if you are interested in
        that piece then you can <b>download the code and browse it : it is fully functional!</b>.
        The classes and methods signature might be a bit different as I am coding while
        writing the article :-) but no major change is to be expected.</p>
    <p style="border-style: solid; border-width: 1px; margin-left: 40px; margin-right: 40px;">
        <u><b>Warning</b></u>: <strong>Before deciding to use this code in your project please
            read carefully the </strong><a href="http://en.wiktionary.org/wiki/paenultimus"><strong>
                paenultimus</strong></a><strong> section. </strong>And if you don&#39;t
        know the word paenultimus then I guess you have to click the link first :-)
    </p>
    <h2>
        Usage</h2>
    <p>
        I have been writing a lot but did not give you, yet, a proper hint on how we can
        actually use all of this. And finally here we are : the moment of truth!
    </p>
    <p>
        The attached source code is including 5 examples for the sake of demonstration.
        Which are injecting an aspect by:</p>
    <ul>
        <li>Intercepting a constructor</li>
        <li>Intercepting methods and properties</li>
        <li>Intercepting events</li>
        <li>Intercepting type initialization</li>
        <li>Intercepting <code>File.ReadAllText(string path)</code></li>
    </ul>
    <p>
        I will demonstrate 2 here, the most and the less obvious</p>
    <h3>
        The most obvious: Intercepting methods and properties
    </h3>
    <p>
        First we need a domain model... Nothing fancy</p>
    <pre lang="C#">
public interface IActor
{
    string Name { get; set; }
    void Act();
}

public class Actor : IActor
{
    public string Name { get; set; }

    public void Act()
    {
        Console.WriteLine("My name is '{0}'. I am such a good actor!", Name);
    }
}
    </pre>
    <p>
        Then we need a <b>concern</b></p>
    <pre lang="C#">
public class TheConcern : IConcern&lt;Actor&gt;
{
    public Actor This { get; set; }

    public string Name 
    {
        set
        {
            This.Name = value + ". Hi, " + value + " you've been hacked";
        }
    }

    public void Act()
    {
        This.Act();
        Console.WriteLine("You think so...!");
    }
}
    </pre>
    <p>
        At application initialization we tell the Registry about our <b>joinpoints</b></p>
    <pre lang="C#">
// Weave the Name property setter
AOP.Registry.Join
    (
        typeof(Actor).GetProperty("Name").GetSetMethod(),
        typeof(TheConcern).GetProperty("Name").GetSetMethod()
    );

// Weave the Act method
AOP.Registry.Join
    (
        typeof(Actor).GetMethod("Act"),
        typeof(TheConcern).GetMethod("Act")
    );    </pre>
    <p>
        And finally we create an object via the Factory</p>
    <pre lang="C#">
var actor1 = (IActor) AOP.Factory.Create&lt;Actor&gt;();
actor1.Name = "the Dude";
actor1.Act();    </pre>
    <p>
        Note that we requested the creation of an <code>Actor</code> class but we can cast
        the result to an interface so let&#39;s use <code>IActor</code> as the class is
        implementing it.</p>
    <p>
        If you run that in a Console application the output will be the following:</p>
    <pre>
    My name is 'the Dude. Hi, the Dude you've been hacked&#39;. I am such a good actor!
   You think so...!    </pre>
    <h3>
        The less obvious: Intercepting <code>File.ReadAllText(string path)</code>
    </h3>
    <p>
        Here we have 2 <i>slight</i> issues:</p>
    <ol>
        <li>the <code>File</code> class is static</li>
        <li>and does not implement any interface</li>
    </ol>
    <p>
        That's where we benefit from the "Yes card"! Remember? There is no runtime type
        checking between the returned proxy and the interface.<br />
        Which means we can create any kind of interface... no one as to implement it anyway:
        neither the <b>target</b> nor the <b>concern</b>. Basically we are only using the
        interface as a contract...</p>
    <p>
        Let&#39;s demonstrate that by creating a fake interface to mimic the static <code>File</code>
        class</p>
    <pre lang="C#">
public interface IFile
{
    string[] ReadAllLines(string path);
}
</pre>
    <p>
        Our <strong>concern</strong></p>
    <pre lang="C#">
public class TheConcern
{
    public static string[] ReadAllLines(string path)
    {
        return File.ReadAllLines(path).Select(x => x + " hacked...").ToArray();
    }
}
</pre>
    <p>
        The registering of <b>joinpoints</b>
    </p>
    <pre>
AOP.Registry.Join
    (
        typeof(File).GetMethods().Where(x => x.Name == "ReadAllLines" && x.GetParameters().Count() == 1).First(),
        typeof(TheConcern).GetMethod("ReadAllLines")
    );
</pre>
    <p>
        And finally execution of the program</p>
    <pre>
var path = Path.Combine(Environment.CurrentDirectory, "Examples", "data.txt");
var file = (IFile) AOP.Factory.Create(typeof(File));
foreach (string s in file.ReadAllLines(path)) Console.WriteLine(s);
</pre>
    <p>
        In this case please note that we can not use the <code>Factory.Create&lt;T&gt;</code>
        method as static types cannot be used as generic arguments.</p>
    <h2>
        References</h2>
    <p>
        In no particular order:</p>
    <ul>
        <li><a href="http://www.qi4j.org/ten-minutes-intro.html">Tutorials from Qi4j</a></li>
        <li><a href="http://msdn.microsoft.com/en-us/library/vstudio/scx1w94y(v=vs.100).aspx">
            Extending RealProxy</a></li>
        <li><a href="http://kozmic.pl/dynamic-proxy-tutorial/">Dynamic Proxy Tutorial (Castle.net)</a></li>
        <li><a href="http://www.codeproject.com/Articles/20884/Introducing-the-LinFu-Framework-Part-I-LinFu-Dynam">
            LinFu.DynamicProxy: A Lightweight Proxy Generator</a></li>
        <li><a href="http://www.codeproject.com/Articles/114178/Add-Aspects-to-Object-Using-Dynamic-Decorator">
            Add aspects using Dynamic Decorator</a></li>
        <li><a href="http://www.dolittle.com/blogs/einar/archive/2008/02/10/implementing-a-clr-profiler-to-act-as-an-aop-interceptor-part-1.aspx">
            Implementing a CLR Profiler to act as an AOP interceptor</a></li>
        <li><a href="http://geekswithblogs.net/imilovanovic/archive/2004/09/23/11589.aspx">Intercepting
            the .Net</a></li>
        <li><a href="http://www.codeproject.com/Articles/42474/AspectF-Fluent-Way-to-Add-Aspects-for-Cleaner-Main">
            AspectF Fluent Way to Add Aspects for Cleaner Maintainable Code</a></li>
    </ul>
    <h2>
        Better to come in Episode 2 !!!</h2>
    <p>
        Mainly we have been able to achieve the primary goal of AOP : implement an aspect
        and register it for execution. <u>TinyAOP is born</u>. But there must be an episode
        2! We have not finished our journey in AOP land yet:</p>
    <ul>
        <li>Reason #1: Who wants to register Joinpoints the way we are now? Not me, for sure!
            With a bit of introspection we can make things much more practical and build something
            that look like a real AOP library. AOP is there to facilitate your life not to introduce
            more pain.</li>
        <li>Reason #2: I promised to introduce you to <strong>mix-ins</strong> and <strong>composition</strong>.
            These matters are still completely uncovered.</li>
        <li>Reason #3: We need <u>performance</u> and <u>stability</u>. Now the code is just
            a proof of concept ( less than 250 lines of code :-) ). It is far too slow when
            we can make it very fast. A bit of error checking would not be bad either.</li>
        <li>Reason #4: We are intercepting almost any kind of class but what about <strong>interfaces</strong>
            interception?? </li>
        <li>Reason #5: Do we really need more reasons ?</li>
    </ul>
    <p>
        <u>Conclusion: </u>We have a nice and tiny prototype which demonstrates the technical
        feasability of doing it purely with managed, non-dynamic, code without weaving,
        etc... In next episode let's bring that to a production-ready, full featured implementation
        ! Guys expect some refactoring :-)</p>
    <h2>
        A few last words, off-topic</h2>
    <p>
        No secret that I am french... Nobody's perfect! While writing this article I was
        googling for a place where the expression "A boire, ou je tue le chien!" would be
        explained and I found that page called "French expressions you won't learn at school".
        I am sure you might find some of these expressions pretty funny so I am sharing
        the link : http://www.globule.org/~gpierre/french.php
        <br />
    </p>
    <br />
    <p>
        A website such as Codeproject is only working because some guys are writing and
        publishing articles. Whatever the reasons why these guys are doing it, they are!
        And that takes <b>a non-negligible amount of work and time</b>.
    </p>
    <p>
        Please <b>do not neglect that time and work:</b><br />
        If you don't like the article please refrain to give your vote of 1 without further
        explanations... I might have wrote a statement which is wrong or false, my english
        surely needs rephrasing, maybe you are expecting more or less explanations, I don&#39;t
        know... It is as simple as that:<b> I don't know if you don't tell! </b>Your <u>justified</u>
        bad ratings are welcome I am not gonna hurt (maybe a bit ;-) ) but it will allow
        me to revise my judgment, make any necessary adjustments or corrections to the article
        and also to improve myself for future ones.</p>
    <p>
        Now if you liked the article, or you are using the code or if you have learned something
        today then <strong>let me know as well</strong> : leave a comment, give me your
        vote (of 5 :-)), drop me an email, connect on LinkedIn... Whatever form of feedback
        is much appreciated!!!</p>
    <p>
        Thanks for reading!</p>
</body>
</html>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Architect
Switzerland Switzerland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions