6

私はC#でAOPを使って非常に興味深い経験をしました。インターセプトされているリターンタイプのリストを持つ関数があり、それはすべてうまくいっています。ただし、インターセプター関数はバリデータースタイルの関数であり、呼び出されてブール値のfalseを返すことにより、実際の関数を防ぐことができます。

したがって、コードは次のようになります。

List<Update> updates = Manager.ValidateAndCreate();

// protected void Save(List<Update> updates) { ....
Save(updates);

メソッドインターセプターは次のようになります

public class ExceptionAdvice : AopAlliance.Intercept.IMethodInterceptor {

    public object Invoke(AopAlliance.Intercept.IMethodInvocation invocation) {

        if (isValid(invocation)) {
            return invocation.Proceed();
        } else {
            return false;
        }
    }

    private bool isValid( ...
 }

検証が失敗した後、更新の値は実際にはリストではなくブール値であるため、ここで何らかのランタイムエラーが発生すると思いましたが、発生しませんでした。

updates.GetType().Name == "Boolean"

だが:

updates is bool == false

したがって、saveは変更された更新のリストを引き続き受け入れ、後で使用しようとすると文句を言います。

では、これはC#のようなタイプセーフな言語でどのように可能でしょうか?ところで、それは春のAOPです。

編集:また、これはコンパイルされ、動作します。私はこれを数回ステップスルーしました。

4

1 に答える 1

6

Spring.Netは、コンパイル時の型チェックをスキップするプロキシクラスを実行時に発行しているため、これが可能であると思います。

基本的に、元のクラスをラップし、新しいメソッド実装を動的に生成するデコレータパターンを実装します。動的に生成されたプロキシメソッドでは、ILを書き込むときに戻り型を変更できますが、.NETでは実行時に型をチェックしないため、これが許可されます。もちろん、コンパイル時にも完全に有効です。これは、静的タイプが実際にはランタイムタイプとは異なる、上記のかなり奇妙なシナリオにつながります。

実際のランタイムタイプをチェックしているため、次のことが当てはまります。実際のランタイムタイプは、場合によってはブール値に解決されます。

updates.GetType().Name == "Boolean"

ただし、変数の静的型をブール値と比較しているため、以下は失敗しますが、そうではありません。

updates is bool == false

Invoke内でタイプを変更しないことをお勧めします。

于 2011-08-27T01:30:02.440 に答える