17

私はアスペクト指向プログラミングのアイデアに不慣れですが、ロギングやレポートなどを処理するためにプロジェクトでそれを使用するアイデアを探求したいと思います。この目的のために、いくつか質問があります。

  • これらの限られた目的のために、わざわざAOPのこのパスを探索する必要がありますか?
  • AOPをサポートする.NETFrameworkにはどのようなものがありますか?
  • これらのフレームワークのどれが流暢なインターフェースをサポートしていますか(私はXML構成が嫌いです):)
4

5 に答える 5

23

PostSharp の Web サイトを見ればわかるように、アスペクト指向プログラミングは単なるログ記録やレポート作成などではありません。個人的には、静的な IL の織り込みはあまり行っていません。主に動的な IL の生成で AOP インターセプターを作成しています。そうするときは、ほとんどの場合、コントロール コンテナーの反転からのリゾルブをラップしてインターセプトするために使用しています。

AOP は、例外処理を改善し、トレースを改善し、トランザクション インターセプトを改善します。

たとえば、NHibernateには一種の AOP がありますが、単純なイベント ハンドラーに関してはコンパイル時に静的です。しかし、エンジン内の特定のイベントについては、インターセプターをアタッチできます (別名、アスペクト、イベントはポイントカットなど) - これを使用して、IoC ビジネス エンティティを使用してドメイン オブジェクトに注入します。

強力な AOP フレームワークにより、一般化が可能になり、さらに強力になり、実行時のオーバーヘッドなしで一般化できるようになります。原則として、いくつかの異なる方法があります

(0)。(実際にはそうではありません) 「プリプロセッサ」AOP 別名 C++ のテンプレート、ifdefs など

  1. リフレクション「AOP」
  2. Reflection.Emit による実行時の IL 生成には、高い信頼が必要です。これは、Castle プロジェクトの DynamicProxy2 がたどった道です。DynamicProxy2 はかなり優れており、多くの作業が行われています! また、afaik PatternsAndPractices Policy Framework もこのアプローチを使用しており、多くの XML を使用していますが、独自のジェネレーターを使用しています。NHibernate は DynProx2 に依存しています。
  3. System.CodeDom.Compiler を使用して実行時に IL コンパイル + Assembly.Load(...) を実行し、作成したアセンブリをロードするには、高い信頼が必要です。Boo.Compiler のような他のコンパイラでコンパイルすることも可能です。これは、「スクリプト化された」方法で呼び出すことができる「グローバル関数アセンブリ」を作成するためですが、現在、AOP から少し離れています。
  4. Profiler API (私に聞かないでください)
  5. ランタイム フレームワークに依存する: MarshalByRef/ContextBoundObject を拡張するリンクを参照し、.Net でリモート処理インフラストラクチャを使用して AOP を実行します。これは非常に複雑で、望ましくない依存関係を導入する可能性があります。
  6. コンパイル後の静的 IL ウィービング、PostSharp、Mono.Cecil には Reflection.Emit に相当するものがありますが、これには Reflection.Emit のような具体的なサブクラス (私の記憶が正しければ) での仮想メソッド呼び出しのバグはなく、喜んで検査します。コードは Assembly.ReflectionOnlyLoad に似ており、IL 操作をそのコードに出力することもできます。これは、かなり低レベルのアプローチを探している場合に適しています。高い信頼は必要ありません。
  7. p/invoke を介して C/C++ へのアンマネージ コールバック用のマネージ コードに拡張ポイントを追加しますが、これには、例外が m/um メモリ境界をうまく越えない (むしろ、アプリケーションを台無しにする) ため、いくつかの考慮が必要です。 Windows でマネージ例外フレームワークを使用して VC++/C# を使用している場合、これは非常にひどいセグメンテーション フォールトになる可能性があります。C# でデリゲートを定義する限り、コールバックを C に渡し、C# から C に p/invoke を渡すことができます。おそらく、C から C# にコールバックを渡すこともできます。拡張ポイントは、おそらく静的または動的な IL ウィーバー + ポイントカットを介して行う必要があります。

トランザクションでの使用法Castle.Facility.AutomaticTransactionManagement.TransactionFacilityを 見て、AOP と DynamicProxy2 のインターセプト機能を使用してトランザクションを処理する優れた方法を確認してください。System.Transcations および System.EnterpriseServices と統合されたトランザクション機能では、トランザクションを管理するために分散トランザクション コーディネーター (COM コンポーネント) を使用しています。また、 Vista カーネル (別名 Server 2008) の TxF および TxR コンポーネントを処理するカーネルへの p/invoke の例が複数あります。これにより、NTFS およびレジストリでトランザクションを使用できるようになり、CRUD を確実に実行できるようになります。 do は ACID であり、ネストされたトランザクションを作成するために System.Transactions ともうまく統合されます。

不変検証で の使用法 パラメータにいくつかの属性を追加することで、コントラクトによる設計にも使用できます。

public void PerformOperation([NotNull, NotEmpty] string value) {
// use string
[NotNull] return new string(' ', 5); // can return with attributes as well
}

現時点での問題は、このメタデータを添付して実行時にチェックするオーバーヘッドです。ただし、DEBUG を使用してコンパイルする場合にのみ制約チェックの側面を適用するように指定すると、このメタデータによってパフォーマンスが大幅に低下することはありません。

公理的証明を検討している場合は、代わりに Sing#/Spec# を参照してください。これはより形式的であり、作業はコンパイラによって行われます。

知っておくべきこと 最も重要な点は、懸念がある場合、つまりメソッドの前後に実行されるコードの一部が制御フローを変更している場合、予期しない型を返す可能性があり、戻りが早すぎるか一般的であるということです。呼び出していたメソッドの意図に沿って動作しないため、デバッグが困難なエラーが発生する可能性があります。

また、いつ、どのアセンブリからリフレクションが発生するかわからないため、属性からの例外のスローにも注意してください。属性への反射は、予期したときに発生しない場合があります。これは、属性に型を付けて慎重にチェックしていたときに起こりました。

また、誰かがアクセスした場合、システムの大部分をリダイレクトするために使用できるグローバルな「ポイントカット」を追加することで、攻撃ベクトルの可能性を開いているという事実にも注意してください。

その他のフレームワークAOP 全般について詳しく知りたい場合は、 Qi4J に関する Rickard Öberg のプレゼンテーションを確認することをお勧めします。これは、AOP 用の Java の非常に優れたフレームワークです (Java では、オブジェクト継承のセマンティクスがわずかに異なりますが、これにより、 C#/F#/Nermle/Boo で使用します。

AOP + アドイン dynamicproxy2 が作成するようなランタイム生成アセンブリでアスペクト指向プログラミングを使用する場合のもう 1 つの興味深い可能性は、それらを使用してアプリケーションの境界を越えるオブジェクトをラップし、それによってアドイン パイプラインの作成を簡素化できることです。Microsoft が 3.5 用の AddIn フレームワークを作成したときにこれを使用することを密かに望んでいましたが、残念ながら静的コード生成の方法を選択したため、開発者にとってアドインの作成にかなり大きなオーバーヘッドが生じました。問題は、完全な AppDomain がアンロードされない限り、AppDomain に「リフレクション以上」にロードされた型を再度アンロードできないことです。

グローバル ガベージ コレクションに AOP を使用する... 共通言語インフラストラクチャ上の Linux/Windows で実行される分散システムで。この論文をダウンロードするのは少し難しかったので、サーバーにアップロードして、どこにあるかを確認しました。

Post Scriptum (DLR ではなく CLR で非標準言語を使用している場合、IL ウィービングは非標準準拠のコードを作成する可能性があります。F# では特に興味深いと思います。言語の利点 (タプルによると) -- コンパイル時に警告を表示したい場合は、アセンブリを [assembly: CLSCompliant] でマークすることができます。)

于 2009-02-18T03:24:45.647 に答える
2

.NET の詳細について話すことはできませんが、AOP と、フックを任意のメソッドにアタッチできるというより一般的な考え方は、他の方法では複雑な問題を解決できる便利な手法です。

一例として、契約による設計があります。いくつかの共通のコントラクトを適用したいメソッドがたくさんあるとしましょう。各メソッドが呼び出される前後に、いくつかの「アドバイス」(AOP 用語) を追加できます。すべてのメソッドにカット アンド ペーストする必要はありません。

テスト中は、内部メソッドで何が起こっているかを知ることが役立つことがよくあります。呼び出された回数と、返されたもの。メソッド自体に気を散らすテスト コードを追加することなく、その監視を行うアスペクトを追加できます。そのメソッドのコードを編集することさえできないかもしれません。

アスペクトがどのように実装されるかに注意してください。一部の実装は精巧なプリプロセッサであり、コードのデバッグがより複雑になる場合があります。言語にスムーズに溶け込む人もいます。動的言語は AOP を非常にうまく処理します。Perl には、AOP 用のAspect.pmと、メソッド フックを実現するためのより一般的なHook::LexWrapがあります。

于 2009-02-18T03:09:12.440 に答える
1

AOPは私にとっても興味深いものです。ロギングとパフォーマンスの監視、レポートは、AOPが処理するように設計されているものであるように思われます。.NETの場合、PostSharpはAOPにとって非常に優れたフレームワークです。

少しだけ実験しましたが、非常にうまく実装されているようです。

于 2009-02-18T02:55:28.963 に答える
1

Post Sharpを見る場合は、CodePlexからGoogleBookDownloaderをダウンロードできます。このプロジェクトはそれを使っていると思います。

于 2009-02-18T03:07:00.433 に答える
0

まったく違うとは思わないでください。AOPは、結合を減らし、凝集度を高め、特定のタイプ1のオブジェクトに単一の責任を与えることで関心の分離を行うことにより、設計を改善(IMO)します。.netの世界から来た場合、PostSharpはカスタム属性を使用してアドバイスを織り込みます。Javaの世界から来た場合は、AspectJと呼ばれるJava拡張機能を使用できます。AOPには、一般的に見られるものよりも多くのアプリケーションがあります。

于 2009-02-18T03:04:05.637 に答える