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开发者_如何学Go 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.
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
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.
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.
精彩评论