Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk()...

47
Weben statt kleben Einführung in die Aspektorientierte Programmierung mit PostSharp Bernd Hengelein Siemens AG

Transcript of Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk()...

Page 1: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Weben statt kleben Einführung in die Aspektorientierte Programmierung mit PostSharp

Bernd Hengelein Siemens AG

Page 2: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Bernd Hengelein

Software Engineer/Architect bei

Siemens Healthcare MR

Co-Lead der .NET User Group Franken

http://berndhengelein.de

http://www.dotnet-day-franken.de/

http://dodnedder.de/

Page 3: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private
Page 4: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

1

Einleitung

Page 5: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

1

Einleitung

2 Warum AOP?

Page 6: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

1

Einleitung

2 Warum AOP?

Beispiele mit PostSharp

3

Page 7: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

1

Einleitung

2 Warum AOP?

Beispiele mit PostSharp

3 4 Fazit / Q&A

Page 8: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

// do sth.

}

private void OnOk()

{

// do sth

}

public event PropertyChangedEventHandler

PropertyChanged;

private void RaisePropertyChanged(string propertyName)

{

PropertyChangedEventHandler propertyChanged = PropertyChanged;

if (propertyChanged != null)

{

propertyChanged(this,

new PropertyChangedEventArgs(propertyName));

}

}

}

public class MainViewModel : INotifyPropertyChanged { private ICommand _acceptTextCommand; private ICommand _okCommand; private string _enteredText; public string EnteredText { get { return _enteredText; } set { _enteredText = value; RaisePropertyChanged("EnteredText"); } } public ICommand AcceptTextCommand { get { if (_acceptTextCommand == null) { _acceptTextCommand = new DelegateCommand(OnAcceptText); } return _acceptTextCommand; } } public ICommand OkCommand { get { if (_okCommand == null) { _okCommand = new DelegateCommand(OnOk); } return _okCommand; } }

Page 9: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

// do sth.

}

private void OnOk()

{

// do sth

}

public event PropertyChangedEventHandler

PropertyChanged;

private void RaisePropertyChanged(string propertyName)

{

PropertyChangedEventHandler propertyChanged = PropertyChanged;

if (propertyChanged != null)

{

propertyChanged(this,

new PropertyChangedEventArgs(propertyName));

}

}

}

public class MainViewModel : INotifyPropertyChanged { private ICommand _acceptTextCommand; private ICommand _okCommand; private string _enteredText; public string EnteredText { get { return _enteredText; } set { _enteredText = value; RaisePropertyChanged("EnteredText"); } } public ICommand AcceptTextCommand { get { if (_acceptTextCommand == null) { _acceptTextCommand = new DelegateCommand(OnAcceptText); } return _acceptTextCommand; } } public ICommand OkCommand { get { if (_okCommand == null) { _okCommand = new DelegateCommand(OnOk); } return _okCommand; } }

Page 10: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

// do sth.

}

private void OnOk()

{

// do sth

}

public event PropertyChangedEventHandler

PropertyChanged;

private void RaisePropertyChanged(string propertyName)

{

PropertyChangedEventHandler propertyChanged = PropertyChanged;

if (propertyChanged != null)

{

propertyChanged(this,

new PropertyChangedEventArgs(propertyName));

}

}

}

public class MainViewModel : INotifyPropertyChanged { private ICommand _acceptTextCommand; private ICommand _okCommand; private string _enteredText; public string EnteredText { get { return _enteredText; } set { _enteredText = value; RaisePropertyChanged("EnteredText"); } } public ICommand AcceptTextCommand { get { if (_acceptTextCommand == null) { _acceptTextCommand = new DelegateCommand(OnAcceptText); } return _acceptTextCommand; } } public ICommand OkCommand { get { if (_okCommand == null) { _okCommand = new DelegateCommand(OnOk); } return _okCommand; } }

Page 11: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

// do sth.

}

private void OnOk()

{

// do sth

}

public event PropertyChangedEventHandler

PropertyChanged;

private void RaisePropertyChanged(string propertyName)

{

PropertyChangedEventHandler propertyChanged = PropertyChanged;

if (propertyChanged != null)

{

propertyChanged(this,

new PropertyChangedEventArgs(propertyName));

}

}

}

public class MainViewModel : INotifyPropertyChanged { private ICommand _acceptTextCommand; private ICommand _okCommand; private string _enteredText; public string EnteredText { get { return _enteredText; } set { _enteredText = value; RaisePropertyChanged("EnteredText"); } } public ICommand AcceptTextCommand { get { if (_acceptTextCommand == null) { _acceptTextCommand = new DelegateCommand(OnAcceptText); } return _acceptTextCommand; } } public ICommand OkCommand { get { if (_okCommand == null) { _okCommand = new DelegateCommand(OnOk); } return _okCommand; } }

Page 12: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

// do sth.

}

private void OnOk()

{

// do sth

}

public event PropertyChangedEventHandler

PropertyChanged;

private void RaisePropertyChanged(string propertyName)

{

PropertyChangedEventHandler propertyChanged = PropertyChanged;

if (propertyChanged != null)

{

propertyChanged(this,

new PropertyChangedEventArgs(propertyName));

}

}

}

public class MainViewModel : INotifyPropertyChanged { private ICommand _acceptTextCommand; private ICommand _okCommand; private string _enteredText; public string EnteredText { get { return _enteredText; } set { _enteredText = value; RaisePropertyChanged("EnteredText"); } } public ICommand AcceptTextCommand { get { if (_acceptTextCommand == null) { _acceptTextCommand = new DelegateCommand(OnAcceptText); } return _acceptTextCommand; } } public ICommand OkCommand { get { if (_okCommand == null) { _okCommand = new DelegateCommand(OnOk); } return _okCommand; } }

PropertyChanged Event feuern

Page 13: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Mülleimerbild

Page 14: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

// do sth.

}

private void OnOk()

{

// do sth

}

public event PropertyChangedEventHandler

PropertyChanged;

private void RaisePropertyChanged(string propertyName)

{

PropertyChangedEventHandler propertyChanged = PropertyChanged;

if (propertyChanged != null)

{

propertyChanged(this,

new PropertyChangedEventArgs(propertyName));

}

}

}

public class MainViewModel : INotifyPropertyChanged { private ICommand _acceptTextCommand; private ICommand _okCommand; private string _enteredText; public string EnteredText { get { return _enteredText; } set { _enteredText = value; RaisePropertyChanged("EnteredText"); } } public ICommand AcceptTextCommand { get { if (_acceptTextCommand == null) { _acceptTextCommand = new DelegateCommand(OnAcceptText); } return _acceptTextCommand; } } public ICommand OkCommand { get { if (_okCommand == null) { _okCommand = new DelegateCommand(OnOk); } return _okCommand; } }

Page 15: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

// do sth.

}

Page 16: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

Trace.TraceInformation("Entering OnAcceptText");

// do sth.

Trace.TraceInformation("Leaving OnAcceptText");

}

Page 17: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

Trace.TraceInformation("Entering OnAcceptText");

ThreadPool.QueueUserWorkItem(

delegate

{

// do sth.

});

Trace.TraceInformation("Leaving OnAcceptText");

}

Page 18: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

Trace.TraceInformation("Entering OnAcceptText");

ThreadPool.QueueUserWorkItem(

delegate

{

// do sth.

_dialogService.ShowDialog("Demodialog", "Press ok to continue.");

});

Trace.TraceInformation("Leaving OnAcceptText");

}

Page 19: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

Trace.TraceInformation("Entering OnAcceptText");

var dispatcher = Dispatcher.CurrentDispatcher;

ThreadPool.QueueUserWorkItem(

delegate

{

// do sth.

dispatcher.BeginInvoke(

new Action(() => _dialogService.ShowDialog("Demodialog",

"Press ok to continue.")));

});

Trace.TraceInformation("Leaving OnAcceptText");

}

Page 20: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

Trace.TraceInformation("Entering OnAcceptText");

var dispatcher = Dispatcher.CurrentDispatcher;

ThreadPool.QueueUserWorkItem(

delegate

{

try

{

// do sth.

dispatcher.BeginInvoke(

new Action(() => _dialogService.ShowDialog("Demodialog",

"Press ok to continue.")));

}

catch (Exception e)

{

// make sure to do proper exception handling, e.g. inform calling thread

Trace.TraceError("Exception caught!");

}

});

Trace.TraceInformation("Leaving OnAcceptText");

}

Page 21: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Wo liegt

das Problem?

Page 22: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

private void OnAcceptText()

{

Trace.TraceInformation("Entering OnAcceptText");

var dispatcher = Dispatcher.CurrentDispatcher;

ThreadPool.QueueUserWorkItem(

delegate

{

try

{

// do sth.

dispatcher.BeginInvoke(

new Action(() => _dialogService.ShowDialog("Demodialog",

"Press ok.")));

}

catch (Exception e)

{

// make sure to do proper exception handling, e.g. inform calling thread

Trace.TraceError("Exception caught!");

}

});

Trace.TraceInformation("Leaving OnAcceptText");

}

Page 23: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Cross-Cutting concerns

Tracing Exception

Handling

Security Threading

Data

Binding

Page 24: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

TracingAspect

RunsOnUIThreadAspect

RunAsyncAspect

HandleExceptionAspect

Cross-Cutting concerns in Aspekte auslagern

Page 25: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Zeig‘ mir den Code…

Demo

Page 26: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

OnMethodBoundaryAspect

OnEntry()

OnSuccess()

OnExit()

OnException()

Page 27: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Wie arbeitet PostSharp?

Source Code

IntermediateAssembly

OutputAssembly

C# Compiler PostSharp

MSBuild

Page 28: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Multicasting

Demo

Page 29: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Lebenszeit von Aspekten

1

Instantiation

2

Validation

3

Compile-Time

Initialization

4

Serialization

Co

mp

ile-T

ime

1

Deserialization

2

Per-Class

Initialization

3

Per-Instance

Initialization

4

Execution

Ru

n-T

ime

Page 30: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Trace Aspekt

verbessern

Demo

Page 31: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Welche Möglichkeiten bietet PostSharp?

Veränderungen

• Methoden einfassen

• Methoden unterbrechen (intercept)

• Eigenschaften unterbrechen

• Felder unterbrechen

• Events unterbrechen

Page 32: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Welche Möglichkeiten bietet PostSharp?

Erweiterung von Klassen

• Interfaces hinzufügen

• Methoden hinzufügen

• Eigenschaften hinzufügen

• Events hinzufügen

• … (siehe PostSharp Dokumentation)

Page 33: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Methoden unterbrechen

(Threading)

Demo

Page 34: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

MethodInterceptionAspect

Methodenaufruf Originalmethode

Methodenaufruf Interception

Aspect Originalmethode

Page 35: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

INotifyPropertyChanged mit Aspekt implementieren

• Implementieren des Interfaces INPC

• Event PropertyChanged definieren

• Methode OnPropertyChanged definieren

• Alle Setter von öffentlichen Eigenschaften

ändern

Page 36: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

INotifyPropertyChanged

Demo

Page 37: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Begriffe: Pointcut, Advice

• Advice: „the what“

– z.B. Überschreiben von OnEntry was soll

gemacht werden

• Pointcut: „the where“

– z.B. bei OnMethodBoundaryAspect alle

Methoden, wenn der Aspekt auf der Klasse ist

Page 38: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Einbinden von PostSharp

• Verfügbar ab Version 2.1

• Unterstützt die Visual Studio

Extension

• Installation im Source Repository

• Einfache Handhabung

Page 39: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Einbinden von PostSharp

• Maximale Eingriffsmöglichkeiten

• Unterstützt die Visual Studio

Extension (ab Version 2.1)

• Installation im Source Repository

Page 40: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Einbinden von PostSharp

• Sehr einfache

Installation

• Unterstützt die Visual

Studio Extension (ab 2.0)

• Keine Installation im

Source Repository (wird

lokal im GAC installiert)

Page 41: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Was bringt‘s?

Weniger

Lines of Code

schreiben

Page 42: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Was bringt‘s?

Mehr

Automatisierung

Page 43: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Was bringt‘s?

Wiederverwendbarkeit

Page 44: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Was bringt‘s?

Weniger

„Boilerplate“ Code

Page 45: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Was kostet‘s?

Längere Buildzeiten

Zusätzliches Tool in der Kette

Page 46: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Fragen?

Page 47: Weben statt kleben · 2011-11-21 · private void OnAcceptText() { // do sth. } private void OnOk() { // do sth } public event PropertyChangedEventHandler PropertyChanged; private

Vielen Dank!

Bernd Hengelein Siemens AG