私は常に私が追加しているクラスを持っています。クラスをOCPに従うようにする - ファクタリング関数をオブジェクトに変換する
これらの新機能がすべて追加されているため、このクラスはオープンクローズではありませんでした。だから私は、これらの関数をRequestオブジェクトにカプセル化することによって、このクラスをこのクラスに対してクローズすることを考えました。私は次のようなものになります:
public abstract class RequestBase{}
public class AddRequest : RequestBase{}
etc...
public class OrderRepository{
public void ProcessRequest(RequestBase request){}
}
これは、OrderRepositoryを拡張用に開き、修正するために閉じたものです。しかし、私はすぐにいくつかの問題に遭遇しました。
1.)そのリクエストが操作する必要があるデータは、ユーザー提供の(ランタイム)と依存性注入供給の両方です。 1つのコンストラクタで両方を満たすことはできません。私はできません:
public class AddRequest{
public AddRequest(IEnumerable<Order> orders, int UserSuppliedContextArg1, DependencyInjectionArg1, DependencyInjectionArg2);
}
と呼んでください。 DIフレームワークが私のためにオブジェクトを「部分的に」構築し、残りをやり直す方法が必要です。私はそれを行う方法は見当たりません。私はこのコンセプトを「変数コンストラクタインジェクション」と呼ぶブログを見ました。
2.)私はこれを2つの別々のクラスに分割することを考えました。ユーザーはRequestContextを作成して記入し、それをリポジトリに渡します。これにより、RequestProcessorが作成されます(より良い名前は考えられません)。私は次のことを考えました:
public abstract class RequestContextBase<T> where T : RequestProcessorBase{}
public class AddRequestContext : RequestContextBase<AddRequestProcessor>
public class OrderRepository{
public void ProcessRequest<T>(RequestBase<T> request){
var requestProcessor = IoC.Create<T>();
}
}
これは良い最初のステップでした。しかし、要求プロセッサは、それが格納している正確なタイプのコンテキストを必要とします。私はここにはありません。私は型に種類の辞書を使用することができますが、それは私のような何かをする必要が終わるオープン・クローズ。だからであることの目的に反し:
public class RequestProcessorBase<TRequestContext, TRequestProcessorBase> where TRequestContext : RequestContextBase<TRequestProcessorBase>
これは奇妙であると私は普通のが好きじゃありませんcuriously recurring template pattern。さらに、コンテキストを埋めるユーザに、それを要求するように依頼するという考えは、ちょうど命名の問題かもしれないが、奇妙に思える。悪いことではありません
public AddRequest{
public AddRequest(DependencyInjectionArg1, DependencyInjectionArg2, ...){}
public void PackArgs(UserSuppliedContextArg1, UserSuppliedContextArg2, UserSuppliedContextArg3, ...){}
}
を、しかし、APIは醜いです:
3)私は上記の、ちょうど持っていることのすべてを取り除くことを考えました。今、このオブジェクトのクライアントは、それを2回「構築」する必要があります。 PackArgsを呼び出すことを忘れてしまった場合は、何らかの例外をスローする必要があります。
私は続けることができますが、これは私が現時点で最も混乱している問題です。何か案は?
これはやや役立ちますが、私の質問はリクエストをカプセル化し、クエリではないことです。さらに、私はリポジトリの背後にあるDBにアクセスしていませんが、おそらく問題ではありません。 – DavidN