views:

1085

answers:

5

Hi

I am just getting started with IoC containers so apologies if this is a stupid question.

I have code like the following in an app

internal static class StaticDataHandlerFactory
    {
        public static IStaticDataHandler CreateHandler(StaticDataUpdate staticDataUpdate)
        {
            if (staticDataUpdate.Item is StaticDataUpdateOffice)
            {
                return new OfficeUpdateHandler();
            }

            if (staticDataUpdate.Item is StaticDataUpdateEmployee)
            {
                return new EmployeeUpdateHandler();   
            }

            if (staticDataUpdate.Item == null)
            {
                throw new NotImplementedException(
                    string.Format("No static data provided"));
            }
            else
            {
                throw new NotImplementedException(
                    string.Format("Unimplemented static data type of {0}", staticDataUpdate.Item.GetType().FullName));
            }
        }
    }

It is basically a simple factory that returns the correct strategy for handling the input data.

Would an IoC container allow me to eliminate code like this? That is to say : would it allow me to dynamically choose a concrete implementation to load based on the type of an input parameter?

Or am I way off course here?

A: 

The short answer is yes, it allows it. This blog post shows a slick way to choose implementation at runtime using Windsor. The author, Ayende, elaborates here and here.

I have not tried this yet, but I expect to soon.

Tim Scott
+2  A: 

You're not far off course at all; the way I understand it, you're pretty close.

The way I would most commonly structure this sort of thing is to turn your Factory class into your IoC container, simply by allowing the UpdateHandlers that are returned to be specified using Dependency Injection. So instead of having the logic in your code that specifies that StaticDataUpdateOffice means to return OfficeUpdateHandler, you can turn your code into simply saying that StaticDataUpdateOffice returns whatever a (newly specified) m_officeUpdateHandler variable contains; so long as your Framework makes sure that you set the value of m_officeUpdateHandler before you invoke your factory, you're good to go. And you can change the value of the m_officeUpdateHandler to anything you want at runtime as your needs change.

This Dependency Injection allows you to have control over the Inversion of Control process; you can have a simple factory that returns your handlers, and you can abstract the logic that controls what handler gets returned to a different location, as appropriate.

Note: my experience with this sort of thing is pretty strongly driven by my (very positive) experience with Spring, and so that may color my interpretation of your question (and the answer).

McWafflestix
A: 

I agree with the other answers here, that yes, you can do it that way. But, why don't you use a generic?

public static IStaticDataHandler CreateHandler<T>( params object[] args )
{...

where args can be passed in as the ctor arguments (to, for example, Activator).

dviljoen
Because generics get resolved at compile time - he's making his decision based on what kind of Item is being carried as cargo, a runtime decision.
Bevan
You do not have to resolve generics at compile time. Look at Type.MakeGenericType() if you don't believe me.
dviljoen
+3  A: 

Actually, although it is possible to replace some of the code with an inversion of control system, it's not obvious to me it's a good idea. Dependency injection tends to be best for configuration of systems, not dynamic creation of objects. To put it a different way, the container itself is a huge global variable and as such should appear in much of your code.

As an aside, the code appears to be violating the Law of Demeter. It appears that the parameter should be of type "StaticDataUpdateItem" rather than "StaticDataUpdate". With that observed, there's a pretty strong argument for rewriting this code as a method call on the StaticDataUpdateItem.

I used IoC quite heavily, but dynamic object creation is still better dealt with using an abstract factory pattern. In short, if you don't like the idea of adding a method to the item itself to generate the handle, the code's probably best left the way it is.

Julian Birch
A: 

I have yet to read any words here that make much sense.

IoC is more for config?

Dynamic object creation is better what? Generics? This is all off topic.

1) IoC is nothing but a nice time saver compared to implementing the 'composition over specialization/inheritance' gospel.

So rule #1 for using an IoC is you should be really tired of having to deal with long constructors that follow the 'bind to contract not implementation'.

Said another way, this is the stratey pattern as the alternative over the template pattern for the same reasons (encapsulate...)... BUT it is more work to create all the extra interface/abstract types and it is more work to do it EVERY time with all the IServiceProvicerThis and IResolverThat ... If you are not tired of having to tediously fulfil code contracts such as:

IInterestingService interesting = ... you get an instance however..

add about three more lines like this..

then

IAmazementService service = new AmazementService(interesting, thesecondstrategy, thethird, etc...)

That gets old. So IoC is never a question because anyone smart enough to code using solid design would know better. Those asking have all the wrong answers.

So if indeed you meet the above then absolutely. IoC containers are on the hook to do as much 'creational' work as you can benefit from letting them deal with. And the most common creational abstraaction over explicit new is Mr. Factory.

Damon