その1では、TransparentPolicyInjectorを使ってアノテーションベースで処理をインジェクションしてた。
この方法だと、100クラスあると100個属性つけてコンテナ側でも100個TransparentPolicyInjectorを設定しないといけない。
これは、とても使う気になれない!と思って調べてみると、楽する方法があった。
MatchingRuleとPolicyDefinitionというものでいけそう。MatchingRuleで、対象にするクラスのルールを作って、PolicyDefinitionでルールに該当するクラスに何の処理を差し込むか決めれる。
早速実験だ。
UnityEdication2という名前でプロジェクトを作って、前回作ったIGreeterとPersonとLoggingHandlerをコピーする。名前空間はUnityEducationの部分をUnityEducation2に変更しておく。
とりあえずさくっと作る。
class Program
{
static void Main(string[] args)
{
IUnityContainer c = new UnityContainer();
// Interceptionの拡張を追加
c.AddNewExtension<Interception>();
// コンテナにマッチングルールを登録する
c.RegisterInstance<NamespaceMatchingRule>(
"test",
new NamespaceMatchingRule("UnityEducation2.Entities"));
// Interceptionの設定
c.Configure<Interception>().
// IGreeterにはTransparentProxyInterceptorを使う
SetInterceptorFor<IGreeter>(new TransparentProxyInterceptor()).
// UnityEducation2.Entities名前空間のクラスに
// LoggingHandlerを適用するポリシーを作成
AddPolicy("EntitiesLoggingPolicy").
AddMatchingRule<NamespaceMatchingRule>("test").
AddCallHandler<LoggingHandler>();
// インスタンスをコンテナに登録
c.RegisterInstance<IGreeter>(new Person { Name = "大田" });
// インスタンスをコンテナから取得して挨拶文を表示
var ohta = c.Resolve<IGreeter>();
Console.WriteLine(ohta.Greet());
}
}
21行目のAddPolicyから3行がポイント。これをすることで、Personクラスへのアノテーションが不要になる。
クラスの数が増えてくると、ぐぐっと楽さ加減が変わってくるかな。
でも残念なのが、SetInterceptorForメソッドは、インターフェース単位でしか指定できない。これは100個あったら100行書けってことなのかな???
とりあえずIBaseみたいなマーカーインターフェースを作って、そいつを必ず実装すること!みたいなルールで実装するようにしてSetInterceptorFor<IBase>(new TransparentProxyInterceptor())をするのが楽なのかな。
好みのやり方ではないけど…
悩ましい。