views:

143

answers:

4

I am building an application which uses an Abstract Factory pattern to allow runtime determination of which subclass of my IHardwareDevice to create based upon how it responds to a request for identification. I might create Hardware1 or Hardware2.

The problem arises in that I want to use a State pattern in these IHardwareDevice objects and I want to have the State be created by the IoC container. Is there a good way to do this without directly calling the IoC container to resolve the State objects with which to hydrate the IHardwareDevice?

Or, am I thinking about this in the wrong way? Because my Factory is pretty much the entry point into this library, is it okay to have this Factory handle instantiating the container for use in the library? I was planning on having the client application instantiate the container and then use it to gain access to which ever parts of the library it requires, such as the Factory.

I am planning to use Windsor as the IoC container, but am at an early enough stage in the project to switch if needed.

+2  A: 

Most IoC containers, including Windsor, has the option to pass explicit dependencies (parameters) to the constructors of the resolved dependencies; when you call the Resolve method.

So yes, you can pass your State object explicitly to the IHardwareDevice instance you are resolving.

driis
Ideally I wanted to avoid having to reference the container directly and call Resolve from within my library. I will be trying the Typed Factory Facility and if that doesn't work for me, will fall back on this option. Thanks!
Darran
+2  A: 

Here's one way it can be done with Autofac 2.2 (http://autofac.org):

First, an enum to discriminate between states (making up some likely values):

public enum DeviceState { Online, Offline }

Then, the state implementations, like:

public class OnlineState : IDeviceState { }

Next, register each state with its corresponding enum key:

var builder = new ContainerBuilder();
builder.RegisterType<OnlineState>().Keyed<IDeviceState>(DeviceState.Online);
builder.RegisterType<OfflineState>().Keyed<IDeviceState>(DeviceState.Offline);
// Register other components here

Finally, the hardware device uses an index to choose states. The implementation of IIndex is provided automatically by the container:

public class Modem : IHardwareDevice
{
    IIndex<DeviceState, IDeviceState> _states;
    IDeviceState _currentState;

    public Modem(IIndex<DeviceState, IDeviceState> states)
    {
         _states = states;
         SwitchOn();
    }

    void SwitchOn()
    {
         _currentState = _states[DeviceState.Online];
    }
}

Hope this helps.

Nick

Nicholas Blumhardt
A: 

Windsor has a very powerful facility for auto-implementing abstract factories - Typed Factory Facility

It is largely convention based, and if the default convention does not suit your needs, you can override it by providing custom ITypedFactoryComponentSelector.

It gives you access to all information you may need to make the decision - what inline arguments you want to pass down the invocation lane, and what component you want to resolve.

Krzysztof Koźmic
A: 

Hey Darran

I think you mixing two design chocies

1- Ioc 2- State Pattern

what you need is a combonation of these pattrens

1- Let DI container play a role of object creation and Life time management 2- Implement a state pattern between your actual Hardware clases.

saurabh