1

I've looked at many posts here and I'm not entirely clear on the answer to this question.

I want to be able to implement an interface with composition and have all the methods be called on the component:

  1. Create an interface for the Component (i.e. Car).
  2. Create a class, implementing the Component (i.e. SimpleCar)
  3. Create another class which implements the Component interface (i.e. create a DeluxeCar which implements the methods by calling them on a SimpleCar member) by calling them on a Component member.

Now the caveat, the important part is I want to be able to do part 3 without writing all the wrapper methods to make DeluxeCar call the methods on SimpleCar. Preferable only needing to add a C# decorator or some C# template magic.

Two solutions I've seen: 1. ExtensionMethods - I believe you can implement a CarComposite interface and place extension methods on it (Similar to what's done here in C. Lawrence Wenham's answer: Multiple Inheritance in C#). However, I don't think that you can make the Composite interface also implement the Component interface. At least I haven't been able to get a working example. Perhaps I am wrong though. 2. Aspect Oriented Programming. Use PostSharp or another AOP framework to do step 3. I haven't been able to find example code on how to do this. Further I would really like to avoid PostSharp as I don't like the license and want a completely free solution. I think PostSharp states you can't do this with their free version anyways (See AspectInheritance http://www.postsharp.net/purchase). A working example for Spring.Net would help a lot.

Can someone please provide an example of #3 please in using standard C# libraries or Spring.net?

Update

h.alex's suggestion is interesting but still doesn't do what I need. Your use of the abstract class is a bit limiting. Imagine having a Boat interface in addition to the Car interface. Then you want to create an AmphibiousVehicle which implements both Boat and Car. In C# there is no multiple inheritance so you can't inherit both the AbstractCar and AbstractBoat class. You are forced to add even more boilerplate and create an AbstractAmphibiousVechicle abstract class as well. This might be fine if you don't have too many different classes. But sometimes you want to create many different classes and mix and match these behaviours. This is pretty common in video games. You might have a ton of different aspects that you want to be able to do with a game object (Push it, Throw it, Collect it, etc.). You will be forced to make many different abstract classes this way, each having a lot of boilerplate.

I want something like this that PostSharp has, but I'd really like to know if there is a framework with a less restrictive license which can do the same. Is this something that can be easily done in Spring.net for example? http://doc.postsharp.net/postsharp-3.0/##PostSharp-3.0.chm/html/T_PostSharp_Aspects_CompositionAspect.htm

http://doc.postsharp.net/postsharp-3.0/Default.aspx#PostSharp-3.0.chm/html/20c81e23-af91-4688-a672-b0f3cce793a9.htm

Community
  • 1
  • 1
Alex Amato
  • 1,591
  • 4
  • 19
  • 32

1 Answers1

1

So, I believe you are asking about inheritance. Well, the vanilla way one could do it is this:

public interface ICar
{
    void ShiftGearUp();
    void ShiftGearDown();
    void SwitchLightsOn();
    void SwitchLightsOff();
    void Brake();
    void Accelerate();
}

public class Car : ICar
{
    public virtual void ShiftGearUp() { }
    public virtual void ShiftGearDown() { }
    public virtual void SwitchLightsOn() { }
    public virtual void SwitchLightsOff() { }
    public virtual void Brake() { }
    public virtual void Accelerate() { }
}

public class DeluxeCar : Car
{
    public override void SwitchLightsOn()
    {
        //calls the implementation in the Car class.
        base.SwitchLightsOn();
        //implement custom behavior.
        this.AdjustCabinAmbientLighting();
    }

    private void AdjustCabinAmbientLighting() { }
}

In this way you only override the behavior you want to change.

But, there is a world famous rule which says prefer composition over inheritance.

It would make us form the solution in this way:

public interface ICar
{
    void ShiftGearUp();
    void ShiftGearDown();
    void SwitchLightsOn();
    void SwitchLightsOff();
    void Brake();
    void Accelerate();
}

public abstract class AbstractCar : ICar
{
    protected ITransmission Transmission;
    protected ILights Lights;
    protected IEngine Engine;
    protected IBrakes Brakes;

    public void ShiftGearUp()
    {
        this.Transmission.ShiftUp();
    }

    public void ShiftGearDown()
    {
        this.Transmission.ShiftDown();
    }

    public void SwitchLightsOn()
    {
        this.Lights.SwitchOn();
    }

    public void SwitchLightsOff()
    {
        this.Lights.SwitchOff();
    }

    public void Brake()
    {
        this.Brakes.Brake();
    }

    public void Accelerate()
    {
        this.Engine.Accelerate();
    }
}

public class Car : AbstractCar
{
    public Car()
    {
        this.Lights = new AcmeLights();
        //todo
        //this.Engine = init engine object;
        //this.Brakes = init brakes object;
        //this.Transmission = init transmission object;
    }
}

public class DeluxeCar : AbstractCar
{
    public DeluxeCar()
    {
        this.Lights = new FancyLights();
        //todo
        //this.Engine = init engine object;
        //this.Brakes = init brakes object;
        //this.Transmission = init transmission object;
    }
}

public interface ITransmission
{
    void ShiftUp();
    void ShiftDown();
}

public interface ILights
{
    void SwitchOn();
    void SwitchOff();
}

public interface IEngine
{
    void Accelerate();
}

public interface IBrakes
{
    void Brake();
}

public class AcmeLights : ILights
{
    private LightSwitch Switch;

    public void SwitchOn() { this.Switch.On(); }
    public void SwitchOff() { this.Switch.Off(); }
}

public class FancyLights : ILights
{
    private LightSwitch Switch;
    private CabinAmbientLightingController AmbientLightingController;

    public void SwitchOn()
    {
        this.Switch.On();
        this.AmbientLightingController.AdjustLightLevel();
    }

    public void SwitchOff()
    {
        this.Switch.Off();
        this.AmbientLightingController.AdjustLightLevel();
    }
}

public class LightSwitch
{
    public void On() { }
    public void Off() { }
}

public class CabinAmbientLightingController
{
    public void AdjustLightLevel() { }
}

Edit: then you can use an dependency injection tool of your choosing to inject the dependencies of the Car and Deluxe car through their constructors. This is "AOP", maybe.

Edit: For that purpose maybe you can use Dynamic Proxy. The famous tutorial is this. Might be a bit of a learning curve (and possibly not the best solution for this problem, but I don't know any others) - but all in all its a great framework and an interesting read.

What I would do, and please mind that my DynProxy is a little rusty, is declare an empty class, like

public class RocketCar
{

}

and then generate a class proxy without target and use interceptors to forward the calls. So, we should write a generic interceptor to which we can inject dependencies (like in the two concrete Cars above). So, we would have only one such class and configure and use it as needed. I believe this should be possible to code within a day, or two :) The idea is the "Class which does not imple­ment the interface" section here. We would make the RocketCar implement IRocket and ICar.

But! To implement many interfaces in one class is not imo the best way to do things! You are breaking the SRP. If we have all these interfaces anyway, why not make the client code reference them by the individual interfaces? After all, if an RocketCar implements ICar, then it's Accelerate method must not be aware it is a part of a different car. In other words, the RocketCar must act in such a way that it is possible for us to substitute the RocketCar with any other ICar implementation wherever it is used. Otherwise we are breaking the LSP.

So, it is good to have the ICar and the IRocket in seperate classes. The specific implementations of these can have concrete type references to each other which model their interaction.

I am not saying you should never have classes implement multiple interfaces, but that should be an exception rather than the rule.

Community
  • 1
  • 1
h.alex
  • 902
  • 1
  • 8
  • 31
  • This is an interesting solution and thanks for the help. But doesn't quite do what I want. See my Update above. – Alex Amato Jul 31 '13 at 02:39