post sharp talk

22
PostSharp AOP in .NET Business Rules + Plumbing = Enterprise Software David Ross W: www.pebblesteps.co m

Upload: willmation

Post on 14-May-2015

935 views

Category:

Documents


0 download

DESCRIPTION

Introduction to Aspect Orientated Programming in .NET using PostSharp

TRANSCRIPT

Page 1: Post Sharp Talk

PostSharpAOP in .NET

Business Rules + Plumbing = Enterprise Software

David RossW: www.pebblesteps.comE: [email protected]

Page 2: Post Sharp Talk

Application ConcernsCore CrosscuttingFunctional

RequirementsDomain/Object

ModelBusiness Logic

Non-functional Requirements

Model needs to provide capability for many different layers

At layer boundariesLoggingValidationSecurityData marshalling

Page 3: Post Sharp Talk

Crosscutting Concerns – PlumbingLogging/Monitoring/AlertingType safety (Beyond value types int, string)

Validation/EnforcementSecurity

Authorisation/AuthenticationData Binding

INotifyPropertyChanged DependencyProperties

TransactionsConcurrency - Locking

Page 4: Post Sharp Talk

Aspects - Reduce noise in sourceMove plumbing out of source, but keep behaviour

the same

AdviceThe duplicated plumbing code we are removingTypically under 30 lines of codeBehaviour that is injected at a join point

Join pointsPlaces within the code where the Aspect is insertedExamples

Entry/Exit of a method or propertyClass’s Type Definition

Page 5: Post Sharp Talk

Aspects Lingo

Point cutLocates Join Points to apply adviceFilter driven – Automatic injection

Find all Methods, of type Setter, in all classes where Namespace equals “Application.Entities”

Attribute driven – Manual injection

Page 6: Post Sharp Talk

Aspects LingoWeavingProcess of injecting functionality back into a

componentCan be performed by

Text post processor – Magic comments can replaced by code

Proxy container – Uses decorator pattern/hooks to allow code to be inserted

Binary manipulation - Modifying assemblies - by replacing and injecting IL code

Page 7: Post Sharp Talk

Compile-time MSIL Injection process

Copyright © by Gael Fraiteur

If Postsharp modifies a type’s signature...•No Intellisense for a referenced projects that are modified•Intellisense for referenced assemblies that are modified

Page 8: Post Sharp Talk

PostSharp WeavingCompile time Weaving - LGPL

Automatically if a component references PostSharp.Laos.dll – Default Install configures MSBuild

Manual application using an MSBuild task

Run time Weaving – GPL/Commercial LicenseManual via PostSharp.Core.dllStatically modify the assembly just before it is

loaded into the domain

Page 9: Post Sharp Talk

Example classpublic class Demo{

public Demo(){ActivityRecorder.Record("In constructor");}public void Foo(){ActivityRecorder.Record("In Foo");}public void StaticFoo(){ActivityRecorder.Record("In StaticFoo");}

}

Page 10: Post Sharp Talk

[Test] public void Verify_Aspect_Called_On_Method_Invocation() {

var d = new Demo ();d.Foo();d.StaticFoo();

ActivityRecorder.AssertActivityOccured("In constructor");

ActivityRecorder.AssertActivityOccured("Calling Void Foo()");ActivityRecorder.AssertActivityOccured("In Foo");

ActivityRecorder.AssertActivityOccured("Calling Void StaticFoo()");ActivityRecorder.AssertActivityOccured("In StaticFoo");

ActivityRecorder.AssertNoMoreActivities();}

Page 11: Post Sharp Talk

Method Invocation - Aspect[Serializable]public class ExampleOnMethodInvocationAspect :

OnMethodInvocationAspect {

public override void OnInvocation(MethodInvocationEventArgs context) {

ActivityRecorder.Record(string.Format("Calling {0}", context.Delegate.Method.Replace(“~”, “”));

// Do I want to continue??

context.Proceed(); }}

Page 12: Post Sharp Talk

Code after Injectionprivate void ~Foo() { ActivityRecorder.Record("In Foo");}

[DebuggerNonUserCode, CompilerGenerated]public void Foo(){

Delegate delegateInstance = new ~PostSharp~Laos~Implementation.~delegate~0(this.~Foo);

MethodInvocationEventArgs eventArgs = new MethodInvocationEventArgs(delegateInstance, null);

~PostSharp~Laos~Implementation.SkillsMatter.PostSharp.Aspects.

ExampleOnMethodInvocationAspect~1.OnInvocation(eventArgs);

}

Page 13: Post Sharp Talk

Filter based Point Cut [assembly:

ExampleOnMethodInvocationAspect(AttributeTargetAssemblies =

"SkillsMatter.PostSharp", AttributeTargetTypes = "SkillsMatter.PostSharp.OnMethodInvocation.*")]

Very simple to apply changes to all business objects in the solution with a single filter...

Page 14: Post Sharp Talk

On Boundary Invocation - Aspect

[Serializable]public class ExampleOnMethodBoundaryAspect : OnMethodBoundaryAspect{

public override void OnEntry(MethodExecutionEventArgs eventArgs) {ActivityRecorder.Record(string.Format("Before {0}",

eventArgs.Method));}

public override void OnExit(MethodExecutionEventArgs eventArgs) {ActivityRecorder.Record(string.Format("After {0}", eventArgs.Method));

}

public override void OnException(MethodExecutionEventArgs eventArgs) {ActivityRecorder.Record(string.Format("After {0}", eventArgs.Method));

}}

Page 15: Post Sharp Talk

[Test] public void Verify_Aspect_Called_On_Method_Boundary() {var e = new Demo();

e.Foo();e.StaticFoo();

ActivityRecorder.AssertActivityOccured("Before Void .ctor()");ActivityRecorder.AssertActivityOccured("In constructor");ActivityRecorder.AssertActivityOccured("After Void .ctor()");

ActivityRecorder.AssertActivityOccured("Before Void Foo()");ActivityRecorder.AssertActivityOccured("In Foo");ActivityRecorder.AssertActivityOccured("After Void Foo()");

ActivityRecorder.AssertActivityOccured("Before Void StaticFoo()");ActivityRecorder.AssertActivityOccured("In StaticFoo");ActivityRecorder.AssertActivityOccured("After Void StaticFoo()");

ActivityRecorder.AssertNoMoreActivities();}

Page 16: Post Sharp Talk

Manual Point Cutpublic class FoodQuestionaire{

[RegularExpressionValidator("^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$")]

public string Postcode { get; set; }

[RangeValidator(0, 5)]public int? LikesDiary { get; set; }[RangeValidator(0, 5)]public int? LikesBeef { get; set; }[RangeValidator(0, 5)]public int? LikesFish { get; set; }

}

Page 17: Post Sharp Talk

public override void OnEntry(MethodExecutionEventArgs eventArgs) {

if (!eventArgs.Method.Name.StartsWith(“set_"))return;

int value = (int)args[0];if (value < LowerBoundary || value > UpperBoundary)

throw new ValidationException("Value must be between " + LowerBoundary + " and “ +

UpperBoundary);

base.OnEntry(eventArgs);}

Page 18: Post Sharp Talk

[Test]public void RangeTest() {

FoodQuestionaire q = new FoodQuestionaire();

q.LikesBeef = 5;Assert.AreEqual(5, q.LikesBeef);Assert.Throws<ValidationException>(() => q.LikesBeef = 100);Assert.Throws<ValidationException>(() => q.LikesBeef = -3);Assert.AreEqual(5, q.LikesBeef);

q.Postcode = "E14 0AN";Assert.AreEqual("E14 0AN", q.Postcode);Assert.Throws<ValidationException>(() => q.Postcode = "Hello World");Assert.AreEqual("E14 0AN", q.Postcode);

}

Page 19: Post Sharp Talk

On Method Boundary can be used for...How long did a method take to execute?Resource Management – Create resource

before a method is called and release afterwardsTransactions – Commit/Rollback as requiredConcurrency – Mutual Exclusion around code

Page 20: Post Sharp Talk

Other AspectsImplement Method Aspect 

Replace a method’s content with the advice in the aspect

Useful for modifying 3rd party components

Composition AspectAllows an interface/state to be injected into a

componentUsed to simulate multiple inheritanceExamples include

Adding .NET Win Form data binding to a POCO Adding Entity Framework interfaces to a POCO

Page 21: Post Sharp Talk

Breaking the BuildAll NHibernate methods must be virtual – Davy Brion

public class RequireVirtualMethodsAndProperties : OnMethodBoundaryAspect   {

public override bool CompileTimeValidate(MethodBase method)   {            if (!method.IsVirtual) {                string methodName = method.DeclaringType.FullName + “.”

+ method.Name;                 var message = new Message(SeverityType.Fatal, “MustBeVirtual”,                    string.Format(“{0} must be virtual”, methodName), GetType().Name);                MessageSource.MessageSink.Write(message);                 return false;            }            return true;        }}

Page 22: Post Sharp Talk

Learn more...Talk’s source code @ www.pebblesteps.com

http://www.postsharp.org/http://davybrion.com/blog/category/postsharp/http://www.codeplex.com/ValidationAspectshttp://www.eclipse.org/aspectj/doc/released/

progguide/

Thanks for listeningQuestions?