2011-06-27 - AOP - .NET User Group Rhein Neckar
-
Upload
johannes-hoppe -
Category
Technology
-
view
2.558 -
download
5
description
Transcript of 2011-06-27 - AOP - .NET User Group Rhein Neckar
AspektOrientierteProgrammierungmit .NET
Eine praktische Einführung
27.06.2011Dipl.-Inf. (FH) Johannes Hoppe
AOP
Architektur und Patterns
01
AOP
PatternsEntwurfsmuster
==unser täglicher Job
AOPBeispiel
View
Controller
Model(Business Layer)
Service Layer
Repository Layer
Data Access Layer
AOP
Aber…
AOPBusiness 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; }}
AOPBusiness 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
AOPBusiness 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; } }}
+ Logging+ Vorbedingungen
AOPBusiness 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; } }
}
AOPBusiness 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; } }}
AOPBusiness Code
+ Logging + Transaktionen + Vorbedingungen + Exception Handling
+ Feature X+ Feature Y+ Feature Z+ …
AOP
Kern-funktionalität
en(Core Concerns)
Seperationof
Concerns
AOP
VS
AOP
Nicht-Funktionale
Anforderungen
(Crosscutting Concerns)
VS
AOP
SecurityException
HandlingTracingMonitoringTransaction
Data BindingThread SyncCachingValidation…
Cross-Cutting Concerns
AOP
OOP
OOP
+ AOP
AOP
Build-Time Run-TimeHybrid
PostSharp
Spring.NETCastleMS Unity
LinFu
AOP
Build-Time: “Statisch” Run-Time: “Dynamisch”
Erfolgt bei Kompilierung
Code wird direkt verändert
Keine Interfaces erforderlich
Zur Laufzeit keine Änderungen
Auch auf Properties, Felder,Events anwendbar
Kann Member und Interfaces hinzufügen
Erfolgt zur Laufzeit
Code bleibt unverändert
Aufruf wird über Proxy umgeleitet
Zur Laufzeit keine Änderungen
Aufruf wird über Proxyumgeleitet
Aspekte zur Laufzeitkonfigurierbar
AOP
Live Coding
02
AOP
AOP
AOP
AOP 1 x 1
03
AOPAspectJ Begriffe
Join PointPointcutAdviceAspect
AOPAspectJ Begriffe
Join PointPointcutAdviceAspect
AOPIL Code Vorher
[LogTimeAspect]public ActionResult Index(){ IEnumerable<NoteWithCategories> notes = this.WebNoteService.ReadAll(); return View(notes);}
AOPIL 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;}
AOP
: OnMethodBoundaryAspect
try{
}catch (Exception e){ }finally{
}
OnEntry
OnSuccess
OnException
OnExit
Originale Methode Aspect Klasse
Method Body
AOPLinks
Spring.NETspringframework.net
Castlecastleproject.org
Unityunity.codeplex.com
PostSharpsharpcrafters.com
Demo Downloadwebnoteaop.codeplex.com
FRAGEN?
Vielen Dank!Johannes Hoppe
AOP
› MethodBoundaryAspect› OnEntry› OnSuccess› OnException› OnExit
› OnExceptionAspect› OnException
› MethodInterceptionAspect› OnInvoke
› LocationInterceptionAspect› OnGetValue› OnSetValue
› EventInterceptionAspect› OnAddHandler› OnRemoveHandler› OnInvokeHandler
› MethodImplementationAspect› OnInvoke
› CompositionAspect› CreateImplementationObject
Aspect- Typen
AOP
Bildnachweise
Ausgewählter Ordner © Spectral-Design – Fotolia.comWarnhinweis-Schild © Sascha Tiebel – Fotolia.comListe abhaken © Dirk Schumann – Fotolia.com3D rendering of an architecture model 2 © Franck Boston –
Fotolia.comHealthcare © ArtmannWitte – Fotolia.comStressed businessman © Selecstock – Fotolia.com