私は、NHibernate をコード ベースに導入するための重要な取り組みの真っ最中です。データベースからロードしたエンティティに依存関係を注入できるように、ある種の DI コンテナーを使用する必要があると考えました。そのコンテナとして Unity を選びました。
Unity の傍受メカニズムを使用してトランザクションの側面をコードに追加することを検討しているので、たとえば次のことができます。
class SomeService
{
[Transaction]
public void DoSomething(CustomerId id)
{
Customer c = CustomerRepository.LoadCustomer(id);
c.DoSomething();
}
}
ハンドラーは、[Transaction]
セッションとトランザクションの作成、トランザクションのコミット (または例外のロールバック) などを処理します。
この種のインターセプトを使用すると、コードのほぼすべての場所で Unity を使用することになるのではないかと心配しています。この方法でアスペクトを導入した場合、 を決して呼び出しnew SomeService()
てはなりません。そうしないと、トランザクションを持たないサービスを取得することになります。これは製品コードでは許容されますが、テストではオーバーヘッドが大きすぎるようです。たとえば、これを変換する必要があります。
void TestMethod()
{
MockDependency dependency = new MockDependency();
dependency.SetupForTest();
var service = SomeService(dependency);
service.DoSomething();
}
これに:
void TestMethod()
{
unityContainer.RegisterType<MockDependency>();
unityContainer.RegisterType<IDependency, MockDependency>();
MockDependency dependency = unityContainer.Resolve<MockDependency>();
dependency.SetupForTest();
var service = unityContainer.Resolve<SomeService>();
service.DoSomething();
}
これにより、使用しているモック オブジェクトごとに 2 行が追加され、かなりの量のコードが作成されます (テストでは多くのステートフル モックを使用するため、テスト クラスに 5 ~ 8 個のモック オブジェクトが含まれることは珍しくありません。時にはそれ以上。)
スタンドアロンの注入はここでは役に立たないと思います。テストで使用するクラスごとに注入を設定する必要があります。これは、テストが作成された後にクラスにアスペクトが追加される可能性があるためです。
ここで、傍受の使用をやめると、次のようになります。
class SomeService
{
public void DoSomething(CustomerId id)
{
Transaction.Run(
() => {
Customer c = CustomerRepository.LoadCustomer(id);
c.DoSomething();
});
}
}
確かにそれほど良くはありませんが、それほど悪くはないようです。
私は自分の貧しい人の傍受を設定することさえできます:
class SomeService
{
[Transaction]
public void DoSomething(CustomerId id)
{
Interceptor.Intercept(
MethodInfo.GetCurrentMethod(),
() => {
Customer c = CustomerRepository.LoadCustomer(id);
c.DoSomething();
});
}
}
その後、インターセプターはクラスの属性を処理できますが、使用してクラスをインスタンス化することはでき、new
機能が失われることを心配する必要はありません。
Unity インターセプトを使用するより良い方法はありますか?オブジェクトのインスタンス化に常に使用する必要はありませんか?