6

のリストを返すリポジトリがあるとしますPost。リポジトリ インターフェイスには、GetAll()それが示唆することを行うメソッドがあります。

ドメインロジックをリポジトリに入れるべきではないという理論に沿ってGetAll()、次のロジックをGetAll()結果に追加できるように、具体的なメソッドへの呼び出しをインターセプトしたいと考えています。

return GetAll().OrderByDescending(p => p.Posted).ToList();

これを傍受したい理由は、(1)クライアントに拡張メソッド(OrderByDescendingまたはその役に立たないラッパー)を呼び出すことを覚えてもらいたくない、毎回呼び出す必要がある、および(2)そうしないためですすべての具体的な実装で、GetAll()結果を順序付けすることを忘れないようにしたい - このロジックを任意のリポジトリの外部の単一の場所に配置したい。

これを行う最も簡単な方法は何ですか?

私はすでにStructureMapを使用しているので、これで傍受できれば、低コストのオプションになる可能性があります。しかし、SM がメソッド呼び出しをインターセプトするとは思いません。オブジェクト インスタンスの作成だけですか?

プロキシまたは mixinパターンに移動する必要がありますか? Castle Dynamic Proxyにオールインする必要がありますか? または、考慮すべき別の方法、またはおそらく組み合わせがありますか?

上記の特定の例に対する具体的な提案に本当に興味があります。私はAOPの初心者なので、優しくしてください。

4

4 に答える 4

13

DynamicProxyオプションを使用しました。思ったより使いやすかったです。

要したのはusing Castle.DynamicProxy;参照だけでした...

少しIInterceptor...

public class PostRepoInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        invocation.Proceed();

        if (invocation.Method.Name.Equals("GetAll", StringComparison.InvariantCultureIgnoreCase))
            invocation.ReturnValue = this.GetModifiedGetAllResult(invocation.ReturnValue);
    }

    private object GetModifiedGetAllResult(object getAllResult)
    {
        return Post.GetOrderedPosts((IList<Post>)getAllResult);
    }
}

StructureMap 構成の 2 つの新しい行:

    public RepoRegistry()
    {
        var pg = new ProxyGenerator();

        For<IPostRepository>()
            .EnrichAllWith(z => pg.CreateInterfaceProxyWithTarget<IPostRepository>(z, new PostRepoInterceptor()));
    }

..そして、それは完了です。GetAll()今、私が望むように動作します。私は今でも慣れ親しんだ方法でインターフェースを使用することができ、すべてを DRY に保ち、DDD 用に分離しています。

サムアンドレに感謝します。

于 2010-12-23T07:11:20.130 に答える
2

AFAIK、StructureMapはオブジェクトの構築のみをインターセプトするため、それを使用しても機能しません。

Castleはわかりませんが、ここでのアイデアはデコレータパターンを適用することだと思います。そのため、前のリンクで説明した手順に従って、サードパーティのライブラリを繰り返さずに自分でそれを行うこともできます。

私はAOPの大ファンではないので、それが私のやり方です。

HTH

于 2010-12-21T08:57:22.643 に答える
0

いいえ、戻り値を変更することはできません。ただし、アスペクト内のターゲットにアクセスして、ターゲットのプロパティを変更できます。すでにリポジトリが定義されていると仮定すると、後処理の側面を追加してターゲット プロパティを変更するコードを次に示します。

IRepository<decimal> Rep = new Repository();
IRepository<decimal> tpRep = (IRepository<decimal>)ObjectProxyFactory.CreateProxy(Rep,
new String[] { "GetAll" },
null,
new Decoration((x, y) =>
{
    Console.WriteLine("Entering " + x.GetType().ToString());
    if (x.GetType().ToString() == "ThirdPartyHR.Repository")
    {
        List<decimal> decimals = ((Repository)x).RepList;
        IEnumerable<decimal> query = decimals.OrderByDescending(num => num, new SpecialComparer()).ToList<decimal>();
        ((Repository)x).RepList = (List<decimal>)query;
    }
}, null));
tpRep.GetAll();
List<decimal> lstRep = Rep.RepList;

必要に応じて、完全な作業コードをお送りします。そして、可能であれば、記事「動的デコレータを使用してアスペクトをオブジェクトに追加する」から返信してください。ここでメッセージが自動的に取得されないためです。

于 2011-01-17T21:26:43.660 に答える
-1

Add Aspects to Object Using Dynamic Decoratorという記事があります。

設計時にクラスにアスペクトを追加するのではなく、実行時にオブジェクトにアスペクトを追加するアプローチについて説明します。それがあなたの望みのようです。

于 2011-01-15T12:41:50.017 に答える