Question

I have a question regarding Castle Dynamic Proxy (I've been using Castle Windsor as IoC framework for quite some time, but have never used the dynamic proxy directly).

I have a couple of interface describing the abilities of classes. For example:

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();
}

And here are the classes implementing them:

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();
}

Additionally, I have further interfaces combining the above capabilities (these are what I refer to as "meta-interfaces"):

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
{
}

Now I want to "cast" (or whatever) the implementing classes to these meta-interfaces and pass them on to consuming methods:

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);
}

In my real world application, I cannot simply let the implementing classes also implement the meta-interfaces because the number of possible combinations is far too big - this is really just an example!

I've been using Cs-Script in the past which has an extension method called "AlignToInterface" which pretty much does what I want to achieve, for example:

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

Unfortunately, I cannot use this here because it complains that the meta-interfaces don't implement the derived methods. I think this is a bug - how could an interface possible implement another interface?!?!

Now, my question is if (and if so, how) similar could be done using Castle Dynamic proxy?

Any help appreciated!

UPDATE: Edited the consuming examples.

Was it helpful?

Solution

If you insist, you can use Castle. The feature you are looking for is called duck typing. Basic idea is that given a class which has the same public API as some interface, or the interface's API is a subset of the API provided by the class, you could use an instance of this class through the interface reference.

You can find examples of implementing the feature with Castle Windsor here and here. As I understand, both of these implementations are just a proof of concept. Another DI framework, supporting duck typing out of the box is LinFu, but it looks like its maintenance is long since abandoned.

Another question is whether you need the duck typing at all. Given the fact that you have an implementation of each interface, you could use generic type parameters' constraints in the following way:

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...
}

And then use it like (given your classes are not abstract):

game.BeatPaperAndLizard(new Scissors());

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

game.BeatScissorsAndLizard(new Rock());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top