Skip to content
Sagi edited this page Apr 9, 2015 · 10 revisions

Let's change a bit the contract that we've created in the Atom Composite example by refactoring the Code method to a property.

using NCop.Mixins.Framework;
using NCop.Composite.Framework;

[TransientComposite]
[Mixins(typeof(CSharpDeveloperMixin))]
public interface IDeveloper
{
    string Code { get; set; }
}

public class CSharpDeveloperMixin : IDeveloper
{
    public string Code { get; set; }
}

We want to apply the aspect on the Code property therefore we need to create a new aspect that is derived from PropertyInterceptionAspect<string>.

When you derive from a property interception aspect you'll get the option to insert pieces of code in several points in the program (a.k.a join points):

  1. OnGetValue - Called when the value of this property is retrieved.
  2. OnSetValue - Called when the value of this property is changed.

Each code piece is called advice. Let's write some code on each advice.

public class SimplePropertyInterceptionAspect : PropertyInterceptionAspect<string>
{
    public override void OnGetValue(PropertyInterceptionArgs<string> args) {
        Console.WriteLine("OnGetValue");
        args.ProceedGetValue();
    }

    public override void OnSetValue(PropertyInterceptionArgs<string> args) {
        Console.WriteLine("OnSetValue");
        args.ProceedSetValue();
    }
}

In order for NCop to apply SimplePropertyInterceptionAspect as an aspect we need to annotate the Code property with PropertyInterceptionAspectAttribute attribute.

using NCop.Mixins.Framework;
using NCop.Composite.Framework;
using NCop.Aspects.Framework;

[TransientComposite]
[Mixins(typeof(CSharpDeveloperMixin))]
public interface IDeveloper
{
    [PropertyInterceptionAspect(typeof(SimplePropertyInterceptionAspect))]
    string Code { get; set; }
}

An aspect can be placed also on the Mixin's property.

public class CSharpDeveloperMixin : IDeveloper
{
    [PropertyInterceptionAspect(typeof(SimplePropertyInterceptionAspect))]
    public string Code { get; set; }
}

The last thing that we have to do is create a CompositeContainer which will handle two things:

  1. Craft the real implementation in runtime.
  2. Act as a Dependency Injection Container that will resolve our type.
using System;
using NCop.Aspects.Framework;
using NCop.Composite.Framework;
using NCop.Mixins.Framework;

class Program
{
    static void Main(string[] args) {
        IDeveloper developer = null;
        var container = new CompositeContainer();

        container.Configure();
        developer = container.Resolve<IDeveloper>();
        developer.Code = "C# coding";
        Console.WriteLine(developer.Code);
    }
}

The expected output should be:
"OnSetValue"
"OnGetValue"
"C# coding"
Your end result of the code should be similar to this:

using System;
using NCop.Aspects.Framework;
using NCop.Composite.Framework;
using NCop.Mixins.Framework;

namespace NCop.Samples
{
    [TransientComposite]
    [Mixins(typeof(CSharpDeveloperMixin))]
    public interface IDeveloper
    {
        [PropertyInterceptionAspect(typeof(SimplePropertyInterceptionAspect))]
        string Code { get; set; }
    }

    public class SimplePropertyInterceptionAspect : PropertyInterceptionAspect<string>
    {
        public override void OnGetValue(PropertyInterceptionArgs<string> args) {
            Console.WriteLine("OnGetValue");
            args.ProceedGetValue();
        }

        public override void OnSetValue(PropertyInterceptionArgs<string> args) {
            Console.WriteLine("OnSetValue");
            args.ProceedSetValue();
        }
    }

    public class CSharpDeveloperMixin : IDeveloper
    {
        public string Code { get; set; }
    }

    class Program
    {
        static void Main(string[] args) {
            IDeveloper developer = null;
            var container = new CompositeContainer();

            container.Configure();
            developer = container.Resolve<IDeveloper>();
            developer.Code = "C# coding";
            Console.WriteLine(developer.Code);
        }
    }
}