-
Notifications
You must be signed in to change notification settings - Fork 7
Event Action Aspect
Let's change a bit the contract that we've created in the Atom Composite
example by adding a OnCodeCompleted
event.
using NCop.Mixins.Framework;
using NCop.Composite.Framework;
[TransientComposite]
[Mixins(typeof(CSharpDeveloperMixin))]
public interface IDeveloper
{
event Action OnCodeCompleted;
void Code();
}
public class CSharpDeveloperMixin : IDeveloper
{
public event Action OnCodeCompleted;
public void Code() {
var onCodeCompleted = OnCodeCompleted;
Console.WriteLine("C# coding");
if (onCodeCompleted != null) {
onCodeCompleted();
}
}
}
We want to apply the aspect on the OnCodeCompleted
event therefore we need to create a new aspect that is derived from EventActionInterceptionAspect
.
When you derive from an event interception aspect you'll get the option to insert pieces of code in several points in the program (a.k.a join points):
- OnAddHandler - Called when a new delegate is added to this event.
- OnInvokeHandler - Called when the event to which the current aspect is applied is fired.
- OnRemoveHandler - Called when a delegate is removed from this event.
Each code piece is called advice. Let's write some code on each advice.
public class SimpleEventInterceptionAspect : EventActionInterceptionAspect
{
public override void OnAddHandler(EventActionInterceptionArgs args) {
Console.WriteLine("OnAddHandler");
args.ProceedAddHandler();
}
public override void OnInvokeHandler(EventActionInterceptionArgs args) {
Console.WriteLine("OnInvokeHandler");
args.ProceedInvokeHandler();
}
public override void OnRemoveHandler(EventActionInterceptionArgs args) {
Console.WriteLine("OnRemoveHandler");
args.ProceedRemoveHandler();
}
}
In order for NCop to apply SimpleEventInterceptionAspect
as an aspect we need to annotate the OnCodeCompleted
event with EventInterceptionAspectAttribute
attribute.
using NCop.Mixins.Framework;
using NCop.Composite.Framework;
using NCop.Aspects.Framework;
[TransientComposite]
[Mixins(typeof(CSharpDeveloperMixin))]
public interface IDeveloper
{
[EventInterceptionAspect(typeof(SimpleEventInterceptionAspect))]
event Action OnCodeCompleted;
void Code();
}
An aspect can be placed also on the Mixin's event.
public class CSharpDeveloperMixin : IDeveloper
{
[EventInterceptionAspect(typeof(SimpleEventInterceptionAspect))]
public event Action OnCodeCompleted;
public void Code() {
var onCodeCompleted = OnCodeCompleted;
Console.WriteLine("C# coding");
if (onCodeCompleted != null) {
onCodeCompleted();
}
}
}
The last thing that we have to do is create a CompositeContainer
which will handle two things:
- Craft the real implementation in runtime.
- 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
{
private static void Main(string[] args) {
IDeveloper developer = null;
var container = new CompositeContainer();
Action codeCompletionAction = () => Console.WriteLine("Code Completed");
container.Configure();
developer = container.Resolve<IDeveloper>();
developer.OnCodeCompleted += codeCompletionAction;
developer.Code();
developer.OnCodeCompleted -= codeCompletionAction;
}
}
The expected output should be:
"OnAddHandler"
"C# coding"
"OnInvokeHandler"
"Code Completed"
"OnRemoveHandler
Your end result of the code should be similar to this:
using NCop.Aspects.Framework;
using NCop.Composite.Framework;
using NCop.Mixins.Framework;
using System;
namespace NCop.Samples
{
[TransientComposite]
[Mixins(typeof(CSharpDeveloperMixin))]
public interface IDeveloper
{
[EventInterceptionAspect(typeof(SimpleEventInterceptionAspect))]
event Action OnCodeCompleted;
void Code();
}
public class CSharpDeveloperMixin : IDeveloper
{
public event Action OnCodeCompleted;
public void Code() {
var onCodeCompleted = OnCodeCompleted;
Console.WriteLine("C# coding");
if (onCodeCompleted != null) {
onCodeCompleted();
}
}
}
public class SimpleEventInterceptionAspect : EventActionInterceptionAspect
{
public override void OnAddHandler(EventActionInterceptionArgs args) {
Console.WriteLine("OnAddHandler");
args.ProceedAddHandler();
}
public override void OnInvokeHandler(EventActionInterceptionArgs args) {
Console.WriteLine("OnInvokeHandler");
args.ProceedInvokeHandler();
}
public override void OnRemoveHandler(EventActionInterceptionArgs args) {
Console.WriteLine("OnRemoveHandler");
args.ProceedRemoveHandler();
}
}
internal class Program
{
private static void Main(string[] args) {
IDeveloper developer = null;
var container = new CompositeContainer();
Action codeCompletionAction = () => Console.WriteLine("Code Completed");
container.Configure();
developer = container.Resolve<IDeveloper>();
developer.OnCodeCompleted += codeCompletionAction;
developer.Code();
developer.OnCodeCompleted -= codeCompletionAction;
}
}
}