2009-02-18 8 views
18

Ich bin ein Neuling in der Idee der aspektorientierten Programmierung, aber ich möchte die Idee, es in meinem Projekt für die Handhabung von Protokollierung, Berichterstattung, etc. zu verwenden, erkunden. Zu diesem Zweck habe ich einige Fragen:Hilfe und Informationen über aspektorientierte Programmierung

  • Sollte ich mich bemühen, diesen Weg des AOP für diese begrenzten Zwecke zu erkunden?
  • Welche .NET Frameworks, die AOP unterstützen, sind verfügbar?
  • Welche dieser Frameworks eine fließend-Schnittstelle unterstützen (me hasst XML config) :)
+0

Was ist fließend Schnittstelle (API?) haben mit XML Config zu tun? –

+0

Eine flüssige Oberfläche kann die XML-Konfiguration ersetzen. siehe Fluent-Nhibernat gegenüber Nhiberat. Wenn die Schnittstelle fließend ist, bedeutet dies, dass sie zum Beispiel neu strukturiert werden kann. –

+0

[Aspektorientierte Programmierung] (http://izlooite.blogspot.com/2010/06/aspect-oriented-programming.html#comment-form) –

Antwort

23

Aspektorientierte Programmierung ist so viel mehr als nur Protokollierung, Berichterstellung und so weiter, wie Sie sehen werden, wenn Sie sich die Website von PostSharp anschauen. Persönlich habe ich nicht so viel statisches IL-Weben gemacht, hauptsächlich dynamische IL-Erzeugung, um AOP-Abfangjäger zu erzeugen, und wenn ich dies getan habe, habe ich es meistens benutzt, um die Auflösung von Inversions-Containern zu umhüllen und abzufangen.

AOP kann die Behandlung von Ausnahmebedingungen verbessern, die Ablaufverfolgung verbessern und das Abfangen von Transaktionen verbessern.

NHibernate hat zum Beispiel eine Art AOP, obwohl es zur Kompilierzeit statisch ist, was die einfachen Event-Handler betrifft; aber für bestimmte Ereignisse in der Engine können Sie Abfangjäger anhängen (aka Aspekte, die Ereignisse sind die Punkt-Kürzungen usw.) - ich benutze das, um zu injizieren, IoC Geschäftsentitäten in meine Domain-Objekte verwendend.

Leistungsstarke AOP-Frameworks ermöglichen es Ihnen, zu verallgemeinern und noch leistungsfähiger können Sie zur Laufzeit ohne Overhead verallgemeinern; im Prinzip haben Sie ein paar verschiedene Möglichkeiten, es zu tun:

(0). (Nicht wirklich) "Pre-Prozessor" AOP aka Vorlagen in C++, etc ifdefs

  1. Reflection "AOP"
  2. IL-Generation zur Laufzeit durch Reflection.Emit erfordert hohe Vertrauen. Dies ist der Pfad, den DynamicProxy2 im Castle-Projekt genommen hat. DynamicProxy2 ist ziemlich nett und es wurde viel gearbeitet! Auch afaik PatternsAndPractices Policy Framework verwendet diesen Ansatz ebenfalls mit viel XML, allerdings mit eigenem Generator. NHibernate ist von DynProx2 abhängig.
  3. Um IL-Kompilierung + Assembly.Load (...) zur Laufzeit durch die Verwendung von System.CodeDom.Compiler, dann lädt Ihre erstellten Assemblys, hohe Vertrauenswürdigkeit. Das Kompilieren mit einem anderen Compiler wie Boo.Compiler ist auch möglich, da es "globale Funktionsassemblies" erstellt, die Sie auf "Skript" -Weise aufrufen können, aber jetzt verlassen wir AOP ein wenig.
  4. Profiler-APIs (fragen Sie mich nicht über sie)
  5. auf dem Runtime Framework Unter Berufung: MarshalByRef/Context see link und mit Hilfe der remoting-Infrastruktur in .Net erstreckt AOP zu tun, die sehr komplex ist und Abhängigkeiten führen Sie könnten nicht wollen.
  6. Post-compile statische IL-Weben, PostSharp und Mono.Cecil hat eine Entsprechung von Reflection.Emit, aber diese hat keine Fehler für virtuelle Methodenaufrufe in konkreten Unterklassen (wenn ich mich richtig erinnere) wie Reflection.Emit und prüft gerne Ihren Code ähnlich Assembly.ReflectionOnlyLoad und erlaubt Ihnen auch, IL-Operationen in diesen Code auszugeben. Dies ist ein guter Kandidat, wenn Sie nach einem eher niedrigen Ansatz suchen. erfordert nicht so viel Vertrauen.
  7. Hinzufügen von Erweiterungspunkten in Ihrem verwalteten Code für nicht verwaltete Rückrufe zu C/C++ über p/invoke, aber dies erfordert einige Überlegungen, da Ausnahmen keine m/um-Speichergrenzen überschreiten (eher wird es Ihre Anwendung durcheinander bringen) und wenn Sie VC++/C# nicht in Windows mit verwaltetem Exception-Framework verwenden, kann dies zu einem starken Seg-Fehler führen. Sie können Callback an C und p/an C von C# übergeben und wahrscheinlich Callbacks von C an C# übergeben, so lange Sie den Delegaten in C# definieren. Die Erweiterungspunkte müssten wahrscheinlich durch einen statischen oder dynamischen IL-Weber + Punkt-Schnitte gemacht werden.

Nutzungen in Transaktionen Werfen Sie einen Blick auf Castle.Facilities.AutomaticTransactionManagement.TransactionFacility für eine schöne Art und Weise Geschäfte Umgang mit AOP und der Abfangen Fähigkeiten von DynamicProxy2 verwenden. Die Transaktionsfunktion, die in System.Transcations und System.EnterpriseServices integriert ist, verwendet den Distributed Transaction Coordinator (COM-Komponente) zum Verwalten von Transaktionen. Außerdem gibt es mehrere Beispiele für p/invoke im Kernel, um auf die TxF and TxR components of the Vista-kernel (aka Server 2008) zu achten, die es erlauben, Transaktionen auf NTFS und in der Registry zu verwenden, wodurch sichergestellt wird, dass CRUD ACID ist, das auch schön in System.Transactions integriert ist geschachtelte Transaktionen erstellen

Verwendungen in unveränderter Verifizierung Sie können sie auch für das vertragliche Design verwenden, indem Sie einige Attribute an Ihre Parameter anhängen.

Das Problem mit diesem im Moment ist der Overhead des Anhängens dieser Metadaten und überprüfen es zur Laufzeit. Sie können jedoch festlegen, dass der Constraint-Checking-Aspekt nur dann angewendet wird, wenn Sie mit DEBUG und dann mit diesen Metadaten kompilieren. Dies würde nicht zu einer erheblichen Verschlechterung der Performance führen.

Wenn Sie nach Axiomatic-Proofs suchen, sehen Sie sich stattdessen Sing #/SpeC# an, da dies formeller ist und die Arbeit vom Compiler erledigt wird.

Dinge zu beachten Der wichtigste Punkt bewusst zu sein, dass, wenn ein Anliegen, das heißt einiges Stück Code, der vor oder nach dem Verfahren ausgeführt wird, wird den Steuerfluss zu verändern, möglicherweise eine unerwartete Art Rückkehr Wenn Sie zu früh zurückkehren oder sich im Allgemeinen nicht so verhalten, wie Sie sie aufgerufen haben, können Fehler auftreten, die schwer zu beheben sind.

Achten Sie auch auf das Werfen von Ausnahmen von Attributen, weil Sie nie wissen, wann oder von welcher Versammlung, Reflexion auftritt; Die Reflexion über Ihr Attribut kann nicht passieren, wenn Sie es erwarten. Dies passierte mir, als ich Typen in Attributen anfügte und sie sorgfältig prüfte.

Achten Sie auch darauf, dass Sie einen möglichen Angriffsvektor öffnen, indem Sie globale "Punkt-Kürzungen" hinzufügen, die, wenn jemand Zugriff darauf hat, verwendet werden können, um große Teile Ihres Systems umzuleiten.

Andere Gerüste Wenn Sie mehr daran interessiert sind, über AOP im Allgemeinen in das Lernen Ich schlage vor, Sie Rickard Präsentationen Öberg Besuche auf Qi4J, es ist ein sehr guter Rahmen in Java für AOP (Java hat etwas anderes Objekt geerbt obwohl Semantik das macht ein klein wenig tricker in C# verwenden/F #/Nermle/Boo was auch immer.

AOP + AddIns eine weitere interessante Möglichkeit, aspektorientierte Programmierung mit Laufzeit generierte Baugruppen wie jene dynamicproxy2 schafft in Verwendung ist, dass Sie kann sie auch verwenden, um Objekte zu umbrechen, die Anwendungsgrenzen überschreiten, die reby vereinfacht die Erstellung einer Add-In-Pipeline. Ich hatte insgeheim gehofft, dass Microsoft das verwenden würde, wenn sie ihr AddIn-Framework für 3.5 erstellten, aber sie entschieden sich leider dafür, den statischen Code-Gen-Weg zu gehen, was für den Entwickler einen ziemlich großen Aufwand beim Erstellen von Add-Ins bedeutete. Das Problem besteht darin, dass ein Typ, der in einer AppDomain für "mehr als Reflektion" geladen wurde, erst wieder entladen werden kann, wenn die vollständige AppDomain entladen ist. Sie müssen 1) über das Plug-in reflektieren, ohne es zu laden Sie lassen viele manuelle Metadaten schreiben oder generieren (und glauben daran) und 2) ein Objekt, das den Punkt an Ihrem Objekt hält, so dass es nicht GCed ist und Sie den Typ nicht kennen (daher die IContract Assembly) und AddInHandle-Klasse) - das könnte wahrscheinlich auf eine nette Art mit einem dynamischen Proxy/AOP gemacht werden.

Verwenden von AOP für globale Garbage Collection ... in einem verteilten System unter Linux/Windows auf der gemeinsamen Sprachinfrastruktur. Das Papier war ein bisschen schwer zu downloaden, also weiß ich I uploaded it to my server wo es ist.

Post Scriptum (Wenn Sie eine Nicht-Standard-Sprache auf der CLR und nicht die DLR IL-Weberei mit vielleicht nicht-standardkonformen Code erstellen. Besonders interessant für F #, denke ich, weil die Verwendung ein Lot von nicht-standard-Code zum großen Vorteil der Sprache (Tupel sagen) - Sie könnten Ihre Assembly mit [Assembly: CLSCompliant] markieren, wenn Sie Kompilierzeit Warnungen davon erhalten möchten.)

+0

wow! großartige Erklärung. was ich mir erhofft hatte und mehr. Vielen Dank! –

+0

ehrfürchtige Kommentare. Sehr schön. – CmdrTallen

1

AOP als auch für mich interessant ist. Es scheint mir, dass Protokollierung und Leistungsüberwachung, Berichterstattung ist sehr viel, was AOP entwickelt ist. Für .NET ist Post Sharp ein sehr guter Rahmen für AOP.

Ich habe nur ein wenig experimentiert, aber es scheint sehr gut umgesetzt zu sein.

0

Denke nicht, dass es etwas völlig anderes ist. AOP verbessert (IMO) Ihr Design, indem es die Kopplung reduziert, die Kohäsion erhöht, die Bedenken trennt, indem Sie einem Objekt eines bestimmten Typs 1 eine einzige Verantwortung geben. Wenn Sie von .net world sind, verwendet PostSharp benutzerdefinierte Attribute, um Ratschläge zu erstellen. Wenn Sie aus der Java-Welt stammen, können Sie die Java-Erweiterung AspectJ verwenden. AOP hat mehr Anwendungen als das, was Sie allgemein sehen.

1

Wenn Sie sich Post Sharp anschauen, können Sie Google Book Downloader von CodePlex herunterladen. Ich denke, dass dieses Projekt es benutzt.

2

Ich kann nicht für die Besonderheiten von .NET sprechen, aber AOP und die allgemeinere Idee, Hooks an beliebige Methoden anhängen zu können, ist eine praktische Technik, die einige ansonsten haarige Probleme lösen kann.

Ein Beispiel ist design by contract. Nehmen wir an, Sie haben eine Reihe von Methoden, auf die Sie einige allgemeine Verträge anwenden möchten. Sie können einen "Ratschlag" (den AOP-Ausdruck) vor und nach dem Aufruf jeder Methode hinzufügen, ohne & in jede Methode einfügen zu müssen.

Während des Tests ist es oft nützlich zu wissen, was in einer internen Methode vor sich geht. Wie oft wurde es genannt und vielleicht, was es zurückgegeben hat. Sie können einen Aspekt hinzufügen, um diese Überwachung durchzuführen, ohne der Methode selbst störenden Testcode hinzufügen zu müssen. Das Bearbeiten des Codes für diese Methode ist möglicherweise nicht möglich.

Nur aufpassen, wie Aspekte implementiert werden. Einige Implementierungen sind aufwendige Vorprozessoren, die das Debuggen Ihres Codes komplizierter machen können. Andere haken sich nahtlos in die Sprache ein. Dynamische Sprachen behandeln AOP sehr gut. Perl hat Aspect.pm für AOP und die allgemeineren Hook::LexWrap Methodenhacken zu erreichen.

Verwandte Themen