【问题标题】:How can multiple interfaces with multiple classes be merged using DynamicProxy?如何使用 DynamicProxy 合并具有多个类的多个接口?
【发布时间】:2010-11-18 12:49:48
【问题描述】:

假设我们有一个从 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 实例,而不用引用特定的名称?

【问题讨论】:

  • 我不记得它是否在任何地方都有记录,但您会看到正确的行为。 ICat 没有目标优先于你的 mixin。看看它是如何工作的:issues.castleproject.org/issue/DYNPROXY-96
  • 好的,所以完整的接口ICat 应该已经由目标或其中一个mixin 实现了。但这不是禁止我实际合并两个接口吗?我想获得一个ICat 的实例(由ICatBaseICatExtension 组合而成),其中部分实现(ICatBase)被分派到一个目标/mixin,而另一个(ICatExtension)被分派到另一个例子。更具体地说,我们将为ICatExtension 提供一个实现,并且ICatBase 应该使用拦截器自动生成。
  • 不,这仅意味着目标优先于混合。只是不要将此界面作为您的目标。为System.Object创建类代理并将这个接口作为附加接口扔给代理,这样它的优先级最低,调用将转到mixins
  • 太棒了!我已将解决方案添加到帖子中。

标签: castle-dynamicproxy


【解决方案1】:

Mixins 是你通常使用的。

【讨论】:

  • 感谢您的指点。我已经编辑了我的帖子,真的可以使用一些指导。
猜你喜欢
  • 2015-12-14
  • 1970-01-01
  • 2018-09-29
  • 1970-01-01
  • 2019-10-12
  • 1970-01-01
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多