0

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.

wexman
  • 1,217
  • 10
  • 19

1 Answers1

1

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());
galenus
  • 2,087
  • 16
  • 24
  • Thanks @galenus, that should get me working. I want to stick to using Castle because I'm using Windsor as IoC Framework, so I already have the Castle.Core assembly loaded. The first example you posted seems simple enough as a starting point. I cannot use the alternative you provided because I'm doing this in a general purpose utility assembly and the object that I'm "ducking" is passed externally (probably even as type object), so I don't have control about that. I just want to be sure that the object implements all the interfaces that I'm using internally... – wexman Oct 29 '13 at 12:58
  • May be I don't get something, but what is the difference between using type parameter constraints and specifying an explicit interface? Once you define the constraints, nothing can enter the method until it implements all the required interfaces. In case of the duck typing, you also have to *duck* the instance, which has a considerable performance cost. Duck typing is usable in cases where you want to mask some class provided externally as an interface you define internally, like "casting" some framework type to user-defined one. – galenus Oct 29 '13 at 13:15
  • Yes, you're right, that wouldn't make much sense. I've edited the examples to be more realistic. The weapons are indeed provided externally, so I cannot make sure they'll implement the required interfaces... Thanks anyway, I'm fine with the solution you provided! – wexman Oct 30 '13 at 07:43