2013-10-29 32 views
0

我有一个关于城堡动态代理的问题(我一直在使用Castle Windsor作为IoC框架很长一段时间,但从未使用动态代理直接)。代理与城堡动态代理元接口

我有一些介绍类的能力的接口。例如:

public interface IBeatScissors 
{ 
    void BeatScissors(); 
} 

public interface IBeatRock 
{ 
    void BeatRock(); 
} 

public interface IBeatPaper 
{ 
    void BeatPaper(); 
} 

public interface IBeatSpock 
{ 
    void BeatSpock(); 
} 

public interface IBeatLizard 
{ 
    void BeatLizard(); 
} 

这里是实现它们的类:

public abstract class Rock : Weapon, IBeatScissors, IBeatLizard 
{ 
    public abstract void BeatScissors(); 
    public abstract void BeatLizard(); 
} 

public abstract class Paper : Weapon, IBeatRock, IBeatSpock 
{ 
    public abstract void BeatRock(); 
    public abstract void BeatSpock(); 
} 

public abstract class Scissors : Weapon, IBeatPaper, IBeatLizard 
{ 
    public abstract void BeatPaper(); 
    public abstract void BeatLizard(); 
} 

public abstract class Lizard : Weapon, IBeatPaper, IBeatSpock 
{ 
    public abstract void BeatPaper(); 
    public abstract void BeatSpock(); 
} 

public abstract class Spock : Weapon, IBeatScissors, IBeatRock 
{ 
    public abstract void BeatScissors(); 
    public abstract void BeatRock(); 
} 

此外,我有进一步的界面结合上述的功能(这些都是我称之为“元接口”):

public interface IBeatScissorsAndLizard : IBeatScissors, IBeatLizard 
{ 
} 

public interface IBeatRockAndSpock : IBeatRock, IBeatSpock 
{ 
} 

public interface IBeatPaperAndLizard : IBeatPaper, IBeatLizard 
{ 
} 

public interface IBeatPaperAndSpock : IBeatPaper, IBeatSpock 
{ 
} 

public interface IBeatScissorsAndRock : IBeatScissors, IBeatRock 
{ 
} 

现在我想以“铸造”(或其他)的实现类,以这些元接口,并通过他们到消费方法:

public abstract class Game 
{ 
    public void BeatScissorsAndLizard(Weapon weapon) 
    { 
     var w = weapon.Duck<IBeatScissorsAndLizard>(); 
     if(w == null) 
      throw new Exception("You can't win!"); 
     w.BeatScissors(); 
     w.BeatLizard(); 
    } 
    public abstract void BeatRockAndSpock(Weapon weapon); 
    public abstract void BeatPaperAndLizard(Weapon weapon); 
    public abstract void BeatPaperAndSpock(Weapon weapon); 
    public abstract void BeatScissorsAndRock(Weapon weapon); 
} 

在我的真实世界的应用程序中,我不能简单地让实现类也实现元接口,因为可能的组合的数量太大 - 这实际上只是一个例子!

我在其中有一个名为“AlignToInterface”的扩展方法,它几乎不会是我想达到的目标,例如过去一直使用Cs-Script

Rock rock = new Rock(); 
IBeatScissorsAndLizard beatem = rock.AlignToInterface<IBeatScissorsAndLizard>(); 

不幸的是,我不能在这里,因为使用此它抱怨元接口不实现派生方法。我认为这是一个错误 - 一个接口怎么可能实现另一个接口?!?!

现在,我的问题是,如果(如果是这样,如何)类似可以使用城堡动态代理?

任何帮助表示赞赏!

更新:编辑消费示例。

回答

1

如果你坚持,你可以使用城堡。您正在查找的功能称为duck typing。基本思想是给定一个具有与某个接口相同的公共API的类,或者该接口的API是该类提供的API的子集,则可以通过接口引用使用此类的一个实例。

您可以在Castle Windsor herehere中找到实现此功能的示例。据我所知,这两种实现只是概念证明。另一个DI框架,支持鸭子打字框是LinFu,但看起来它的维护时间很长,因为放弃了。

另一个问题是你是否需要鸭子打字。鉴于你有每个接口的实现,你可以通过以下方式使用泛型类型参数的约束:

public abstract class Game 
{ 
    public abstract void BeatScissorsAndLizard<T>(T weapon) 
     where T : IBeatScissors, IBeatLizard; 

    public abstract void BeatPaperAndLizard<T>(T weapon) 
     where T : IBeatPaper, IBeatLizard; 

    //more here... 
} 

,然后用它像(假设你的类不是抽象的):

game.BeatPaperAndLizard(new Scissors()); 

//this does not compile: 
//game.BeatScissorsAndLizard(new Spock()); 

game.BeatScissorsAndLizard(new Rock()); 
+0

谢谢@galenus,应该让我工作。我想坚持使用Castle,因为我使用Windsor作为IoC Framework,所以我已经加载了Castle.Core程序集。你发布的第一个例子似乎很简单,作为一个起点。我无法使用您提供的替代方案,因为我在通用实用程序集合中执行此操作,而我“躲避”的对象在外部传递(可能甚至是作为类型对象),所以我对此没有控制权。我只想确保该对象实现了我在内部使用的所有接口... – wexman

+0

可能我没有得到某些东西,但使用类型参数约束和指定显式接口之间有什么区别?一旦你定义了约束,在它实现所有必需的接口之前,什么都不能进入该方法。在鸭子打字的情况下,你也必须*鸭子*这个实例,这具有相当大的性能成本。如果您想将外部提供的某个类作为您在内部定义的接口进行屏蔽,例如将某些框架类型“投射”到用户定义的类型,那么鸭子键入可用。 – galenus

+0

是的,你说得对,那没什么意义。我编辑过的例子更加真实。这些武器确实是在外部提供的,所以我不能确定他们会实现所需的接口......感谢无论如何,我很满意您提供的解决方案! – wexman

相关问题