使用Castle Dynamic Proxy代理元接口

时间:2013-10-29 07:31:54

标签: c# castle-dynamicproxy

我有一个关于Castle Dynamic Proxy的问题(​​我已经使用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);
}

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

我过去一直在使用Cs-Script,它有一个名为“AlignToInterface”的扩展方法,它实际上是我想要实现的目标,例如:

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

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

现在,我的问题是,如果(如果是这样,如何)使用Castle Dynamic代理可以完成类似的工作?

任何帮助表示赞赏!

更新:编辑了消费示例。

1 个答案:

答案 0 :(得分:1)

如果你坚持,你可以使用Castle。您要查找的功能称为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());