以下に示すように、ICatBase と ICatExtension から派生したインターフェイス ICat があるとします。CatBase と CatExtension の両方の異なるインターフェイスに対して、実装が利用可能です。Castle の DynamicProxy を使用して、これらを ICat のインスタンスにマージするにはどうすればよいですか?
ICatExtension が CatExtension によって実装され、ICatBase がインターセプターによって「実装」されているプロキシを作成することは可能ですか? これはどのように達成できますか?
public interface ICatBase
{
string Name { get; set; }
int Age { get; set; }
}
public interface ICatExtension
{
string Description { get; }
}
public interface ICat : ICatBase, ICatExtension
{
}
public class CatBase : ICatBase
{
public string Name { get; set; }
public int Age { get; set; }
}
public class CatExtension : ICatExtension
{
public string Description
{
get { return "Furry"; }
}
}
編集
ミックスインを使用してこれを機能させようとしましたが、以下のコードでは NotImplementedException が発生します。
var generator = new ProxyGenerator();
var options = new ProxyGenerationOptions();
options.AddMixinInstance(new CatBase());
options.AddMixinInstance(new CatExtension());
var cat = generator.CreateInterfaceProxyWithoutTarget<ICat>(options);
cat.Name = "Joey";
これは DynamicProxy2 エラーです: ターゲットを持たないメソッド 'Void set_Name(System.String)' に指定されたインターセプターはありません。ターゲットなしでメソッドを呼び出す場合、「続行」する実装はなく、実装を模倣するのはインターセプターの責任です (戻り値の設定、引数の出力など)。
呼び出しをインターセプトして正しいインターフェイスにディスパッチするカスタム インターセプターを作成することもできますが、もっと簡単で優れた方法が必要だと思います。私は正しいですか?
編集#2
ありがとう、クシシュトフ!以下の行を使用することが解決策でした。
var generator = new ProxyGenerator();
var options = new ProxyGenerationOptions();
options.AddMixinInstance(new CatBase());
options.AddMixinInstance(new CatExtension());
var cat = (ICat)generator.CreateClassProxyWithTarget(typeof(object), new[] { typeof(ICat)}, new object(), options);
編集#3
最後のステップとして、Windsor コンテナーを構成して、この例からプロキシーを作成しました。これを行うことができた唯一の方法は、「Cat」という名前を指定し、名前を指定してICat
後でインターフェースにキャストすることで System.Object のインスタンスを解決することでした。
WindsorContainer container = new WindsorContainer();
container.Register(
Castle.MicroKernel.Registration.Component.For<object>().
Named("Cat").
Proxy.AdditionalInterfaces(typeof (ICat)).
Proxy.MixIns(new CatBase()).
Proxy.MixIns(new CatExtension())
);
var cat = (ICat)container.Resolve(typeof(object), "Cat");
特定の名前を参照せずに、コンテナーに ICat インスタンスを要求できる、よりエレガントな方法はありますか?