Upload
johannes-hoppe
View
2.699
Download
0
Embed Size (px)
DESCRIPTION
Citation preview
12.04.2012
Dipl.-Inf. (FH) Johannes Hoppe
AOP mit .NET
Architektur und Patterns
01
Patterns software craftsmanship
Business Code
public class CustomerProcesses
{
public void RentBook( int bookId, int customerId )
{
Book book = Book.GetById( bookId );
Customer customer = Customer.GetById( customerId );
book.RentedTo = customer;
customer.AccountLines.Add(
string.Format( "Rental of book {0}.", book ), book.RentalPrice
);
customer.Balance -= book.RentalPrice;
}
}
Business Code
Business Code
public class CustomerProcesses
{
public void RentBook( int bookId, int customerId )
{
Book book = Book.GetById( bookId );
Customer customer = Customer.GetById( customerId );
book.RentedTo = customer;
customer.AccountLines.Add(
string.Format( "Rental of book {0}.", book ), book.RentalPrice
);
customer.Balance -= book.RentalPrice;
}
}
+ Logging
Business Code
internal class CustomerProcesses
{
private static readonly TraceSource trace =
new TraceSource( typeof (CustomerProcesses).FullName );
public void RentBook( int bookId, int customerId )
{
trace.TraceInformation(
"Entering CustomerProcesses.CreateCustomer( bookId = {0},
customerId = {1} )",
bookId, customerId );
try
{
Book book = Book.GetById( bookId );
Customer customer = Customer.GetById( customerId );
book.RentedTo = customer;
customer.AccountLines.Add(
string.Format( "Rental of book {0}.", book ), book.RentalPrice );
customer.Balance -= book.RentalPrice;
trace.TraceInformation(
"Leaving CustomerProcesses.CreateCustomer( bookId = {0}, customerId = {1} )",
bookId, customerId );
}
catch ( Exception e )
{
trace.TraceEvent( TraceEventType.Error, 0,
"Exception: CustomerProcesses.CreateCustomer(
bookId = {0}, customerId = {1} ) failed : {2}",
bookId, customerId, e.Message );
throw;
}
}
}
+ Logging
+ Vorbedingungen
Business Code
internal class CustomerProcesses
{
private static readonly TraceSource trace =
new TraceSource(typeof(CustomerProcesses).FullName);
public void RentBook(int bookId, int customerId)
{
if (bookId <= 0) throw new ArgumentOutOfRangeException("bookId");
if (customerId <= 0) throw new ArgumentOutOfRangeException("customerId");
trace.TraceInformation(
"Entering CustomerProcesses.CreateCustomer( bookId = {0}, customerId = {1} )",
bookId, customerId);
try
{
Book book = Book.GetById(bookId);
Customer customer = Customer.GetById(customerId);
book.RentedTo = customer;
customer.AccountLines.Add(string.Format("Rental of book {0}.", book),
book.RentalPrice);
customer.Balance -= book.RentalPrice;
trace.TraceInformation(
"Leaving CustomerProcesses.CreateCustomer( bookId = {0},
customerId = {1} )“, bookId, customerId);
}
catch (Exception e)
{
trace.TraceEvent(TraceEventType.Error, 0,
"Exception: CustomerProcesses.CreateCustomer( bookId = {0},
customerId = {1} ) failed : {2}",
bookId, customerId, e.Message);
throw;
}
}
}
Business Code
+ Logging + Transaktionen
+ Vorbedingungen
internal class CustomerProcesses
{
private static readonly TraceSource trace =
new TraceSource(typeof(CustomerProcesses).FullName);
public void RentBook(int bookId, int customerId)
{
if (bookId <= 0)
throw new ArgumentOutOfRangeException("bookId");
if (customerId <= 0)
throw new ArgumentOutOfRangeException("customerId");
trace.TraceInformation(
"Entering CustomerProcesses.CreateCustomer( bookId = {0},
customerId = {1} )“, bookId, customerId);
try
{
for (int i = 0; ; i++)
{
try
{
using (var ts = new TransactionScope())
{
Book book = Book.GetById(bookId);
Customer customer =
Customer.GetById(customerId);
book.RentedTo = customer;
customer.AccountLines.Add(
string.Format("Rental of book {0}.", book),
book.RentalPrice);
customer.Balance -= book.RentalPrice;
ts.Complete();
}
break;
}
catch (TransactionConflictException)
{
if (i < 3)
continue;
else
throw;
}
}
trace.TraceInformation(
"Leaving CustomerProcesses.CreateCustomer(
bookId = {0}, customerId = {1} )",
bookId, customerId);
}
catch (Exception e)
{
trace.TraceEvent(TraceEventType.Error, 0,
"Exception: CustomerProcesses.CreateCustomer( bookId = {0},
customerId = {1} ) failed : {2}",
bookId, customerId, e.Message);
throw;
}
}
}
Business Code
+ Logging + Transaktionen
+ Vorbedingungen + Exception Handling
internal class CustomerProcesses
{
private static readonly TraceSource trace =
new TraceSource(typeof(CustomerProcesses).FullName);
public void RentBook(int bookId, int customerId)
{
if (bookId <= 0) throw new ArgumentOutOfRangeException("bookId");
if (customerId <= 0)
throw new ArgumentOutOfRangeException("customerId");
try
{
trace.TraceInformation(
"Entering CustomerProcesses.CreateCustomer(
bookId = {0}, customerId = {1} )",
bookId, customerId );
try
{
for ( int i = 0;; i++ )
{
try
{
using ( var ts = new TransactionScope() )
{
Book book = Book.GetById( bookId );
Customer customer = Customer.GetById( customerId );
book.RentedTo = customer;
customer.AccountLines.Add(
string.Format( "Rental of book {0}.", book ),
book.RentalPrice );
customer.Balance -= book.RentalPrice;
ts.Complete();
}
break;
}
catch ( TransactionConflictException )
{
if ( i < 3 )
continue;
else
throw;
}
}
trace.TraceInformation(
"Leaving CustomerProcesses.CreateCustomer(
bookId = {0}, customerId = {1} )",
bookId, customerId );
}
catch ( Exception e )
{
trace.TraceEvent( TraceEventType.Error, 0,
"Exception: CustomerProcesses.CreateCustomer(
bookId = {0}, customerId = {1} ) failed : {2}",
bookId, customerId, e.Message );
throw;
}
}
catch ( Exception e )
{
if (ExceptionManager.Handle(e)) throw;
}
}
}
Business Code
+ Logging + Transaktionen
+ Vorbedingungen + Exception Handling
+ Feature X
+ Feature Y
+ Feature Z
+ …
Kern-
funktionalitäten (Core Concerns)
Seperation
of Concerns
VS
Nicht-
Funktionale
Anforderungen (Crosscutting Concerns)
VS
Security
Exception Handling
Tracing
Monitoring
Transaction
Data Binding
Thread Sync
Caching
Validation
…
Cross-Cutting Concerns
OOP
OOP
+ AOP
Build-Time Run-Time Hybrid
PostSharp
Spring.NET
Castle
MS Unity LinFu
Erfolgt bei Kompilierung
Code wird direkt verändert
Zur Laufzeit keine Änderungen
Auch auf Properties, Felder,
Events anwendbar
Keine Interfaces erforderlich
Erfolgt zur Laufzeit
Code bleibt unverändert
Zur Laufzeit Änderungen möglich
Aufruf wird über Proxy
umgeleitet
idR. Interfaces erforderlich (Proxy)
Build-Time: “Statisch” Run-Time: “Dynamisch”
Live Coding
02
AOP 1 x 1
03
AspectJ Begriffe
Join Point
Pointcut
Advice
Aspect
AspectJ Begriffe
Join Point
Pointcut
Advice
Aspect
IL Code Vorher
[LogTimeAspect]
public ActionResult Index()
{
IEnumerable<NoteWithCategories> notes =
this.WebNoteService.ReadAll();
return View(notes);
}
IL Code Nachher
public ActionResult Index()
{
ActionResult CS$1$2__returnValue;
MethodExecutionArgs CS$0$3__aspectArgs =
new MethodExecutionArgs(null, null);
<>z__Aspects.a68.OnEntry(CS$0$3__aspectArgs);
try
{
IEnumerable<NoteWithCategories> notes =
this.WebNoteService.ReadAll();
ActionResult CS$1$0000 = base.View(notes);
CS$1$2__returnValue = CS$1$0000;
}
finally
{
<>z__Aspects.a68.OnExit(CS$0$3__aspectArgs);
}
return CS$1$2__returnValue;
}
: OnMethodBoundaryAspect
try { } catch (Exception e) { } finally { }
OnEntry
OnSuccess
OnException
OnExit
Originale Methode Aspekt Klasse
Method Body
Installation
04
www.sharpcrafters.com/postsharp/download
nuget http://nuget.org/packages/PostSharp
Spring.NET springframework.net
Castle castleproject.org
Unity unity.codeplex.com
PostSharp sharpcrafters.com
Demo Download webnoteaop.codeplex.com
FRAGEN?
Bis bald › 10.05.2012 – .NET UG Karlsruhe: NoSQL
› 14.05.2012 – .NET Developer Conference (DDC)
.Nürnberg: NoSQL
Vielen Dank!
› MethodBoundaryAspect
› OnEntry
› OnSuccess
› OnException
› OnExit
› OnExceptionAspect
› OnException
› MethodInterceptionAspect
› OnInvoke
› LocationInterceptionAspect
› OnGetValue
› OnSetValue
› EventInterceptionAspect
› OnAddHandler
› OnRemoveHandler
› OnInvokeHandler
› MethodImplementationAspect
› OnInvoke
› CompositionAspect
› CreateImplementationObject
Primitive Aspekt-Typen
Bildnachweise
Ausgewählter Ordner © Spectral-Design – Fotolia.com
Warnhinweis-Schild © Sascha Tiebel – Fotolia.com
Liste abhaken © Dirk Schumann – Fotolia.com
3D rendering of an architecture model 2 © Franck Boston – Fotolia.com
Healthcare © ArtmannWitte – Fotolia.com
Stressed businessman © Selecstock – Fotolia.com
Funny cartoon boss © artenot – Fotolia.com