3

I want to implement IOC in my application but i am confused, in my application i have multiple concrete classes which implement an interface. Consider this scenario:-

I have an Inteface ICommand and following concrete types which implement this interface:-

  • AddAddress
  • AddContact
  • RemoveAddress
  • RemoveContact

Basically user performs all this action in UI and then List is passed to the service layer where each command is executed.

So in GUI layer I will write

ICommand command1 = new AddAddress();
ICommand command2 = new RemoveContact();

In command manger

List<ICommand> listOfCommands = List<ICommand>();
listOfCommands.Add(command1);
listOfCommands.Add(command2);

Then finally will pass listOfCommands to service layer.

Now as per my understanding of IOC is only one concrete class is mapped to the interface. And we use this syntax to get our concrete type from StructureMap container.

ICommand command = ObjectFactory.GetInstance<ICommand>();

How should i implement IOC in this scenario?

TrueDesign
  • 31
  • 2

3 Answers3

3

In this scenario you're better off making your commands into value objects, i.e. not created by the IoC container:

class AddAddressCommand {
    public AddAddressCommand(string address) {
        Address = address;
    }
    public string Address { get; private set; }
}

When you create a command, you really do want a specific implementation, and you want to parameterise it precisely, both concerns that will work against the services of the IoC container. This will become even more relevant if you decide at some point to serialize the command objects.

Instead, make the service-layer components that execute the commands into IoC-provided components:

class AddAddressHandler : IHandler<AddAddressCommand> {
    public AddAddressHandler(ISomeDependency someDependency) { ... }
    public void Handle(AddAddressCommand command) {
        // Execution logic using dependencies goes here
    }
}

In your case, the component that accepts the list of commands to execute will need to resolve the appropriate handler for each command and dispatch the command object to it.

There's some discussion of how to do this with Windsor here: http://devlicious.com/blogs/krzysztof_kozmic/archive/2010/03/11/advanced-castle-windsor-generic-typed-factories-auto-release-and-more.aspx - the community supporting your IoC container of choice will be able to help you with its configuration.

Nicholas Blumhardt
  • 30,271
  • 4
  • 90
  • 101
1

As mentioned by Mark, StructureMap will allow you to set up and call named instances of an interface:

ObjectFactory.Initialize(x =>
{
   x.For<ISomeInterface>().Add<SomeImplementation>().Named("SomeName");
}

You can still add a default instance for that particular interface, of course:

ObjectFactory.Initialize(x =>
{
  x.For<ISomeInterface>().Add<DefaultImplementation>();       
  x.For<ISomeInterface>().Add<SomeImplementation>().Named("SomeName");
}

When you call ObjectFactory.GetInstance<ISomeInterface>(); the default instance (the one initialized with Use instead of Add) is the one that will be returned.

So in your case, the set up would look something like:

ObjectFactory.Initialize(x =>
{
   // names are arbitrary
   x.For<ICommand>().Add<AddAddress>().Named("AddAddress");
   x.For<ICommand>().Add<RemoveContact>().Named("RemoveContact");
}

These would be called as pointed out by Mark:

ObjectFactory.GetNamedInstance<ICommand>("AddAddress");
ObjectFactory.GetNamedInstance<ICommand>("RemoveContact");

Hope this helps.

Sergi Papaseit
  • 15,999
  • 16
  • 67
  • 101
0

Most IOC containers allow you to register "named instances" of interfaces, allowing you to register several implementations of ICommand, each with its own unique name. In StructureMap, you request them like this:

ObjectFactory.GetNamedInstance<ICommand>("AddAddress");

Have a look at this question to see how you setup the container in StructureMap.

Community
  • 1
  • 1
Mark Heath
  • 48,273
  • 29
  • 137
  • 194