假设我们有一个从 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"; }
}
}
编辑
我一直在尝试使用 mixins 来完成这项工作,但下面的代码会导致 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 实例,而不参考特定名称?