0

I have put this kind of pattern in my code for instantiating business objects:

// UI or Business level code
public class SomeClass
{
    IOrderFactory orderFactory;

    public SomeClass(IOrderFactory orderFactory)
    {
        this.orderFactory = orderFactory
    }

    public void SomeMethod()
    {
        var newOrder = orderFactory.CreateOrder();
        // Do stuff with new object        
    }
}

// In an interfaces only project
public interface IOrderFactory
{
    Order CreateOrder();
}

// In an implementation project (not seen by most other modules)
public class OrderFactory
{
    public Order CreateOrder()
    {
        return new Order();
    }
}

We currently use Unity to create the IOrderFactory object, but i am wondering if Unity (IOC) can be used to to generate the Order object itself.

Something like unityContainer.Resolve<IOrder>() and have it make a new one each time?

Would that work? We use unity for our services and functional (ie ViewModels, Helpers) classes. But we have never used it to to create business objects (like Customer or Order.)

Vaccano
  • 78,325
  • 149
  • 468
  • 850
  • You should typically not resolve business objects from your container, and it is even questionable whether you would even need a factory for this. Here's a related question: http://stackoverflow.com/questions/4835046/why-not-use-an-ioc-container-to-resolve-dependencies-for-entities-business-objec – Steven Nov 11 '12 at 12:07

3 Answers3

3

In my opinion, this all depends on how complex it is to build an instance of a given object (ie. WizBang), and how often it will change.

If the implementation of IWizBang will always be WizBang, or if creating a WizBang instance just involves calling the default constructor, then introducing an IOC container is overkill ... you can easily make a factory method to generate the method for you. Developers often forget that configuration complexity can burden developers who are new to a project, or even developers who don't often have to add a new entity which needs to be configured.

Joel Martinez
  • 46,929
  • 26
  • 130
  • 185
  • Good point. (Note: I changed my example from WizBang to Order to show that this was a domain object.) – Vaccano Nov 09 '12 at 17:14
1

New answer

Indeed, you'll reduce builerplate code. Domain classes are no different from any other class. Instead of having a factory class you could register the mapping from the interface to the concrete type and provide ctor parameters if needed. See http://msdn.microsoft.com/en-us/library/ff648211.aspx

Old answer

Resolving an object through any container will always be slower than invoking a virtual method and invoking a constructor. It is not in raw performance where you'll get a benefit from a DI container.

fsimonazzi
  • 2,975
  • 15
  • 13
1

I would keep the IOrderFactory. DI containers are fabulous at giving you services, but when you need an entity (something where the specific object identity is important) using the container often gets problematic.

There are a couple reasons I would do this:

  1. Creating entities tends to require the data for that entity (order ids, line items, etc), which are different for each time you create it. This gets difficult and awkward to do with the container.
  2. In order to do this will require that you give the container instance to your business logic. You really don't want your code depending directly on the container except at the composition root. In my experience, seeing lots of IUnityContainer dependencies is a warning sign.

However, you can take advantage of the container - keep the IOrderFactory as a dependency, and then inject the factory into the container. You can then inject whatever services needed to create an order into the factory itself to hold onto. You could also inject the container into the factory.

Another option, if it really is the case that you can create an order with no special parameter values beyond what you've configured, would be to inject a Func - a factory function. This will be generated by the container at runtime and will call back into container.Resolve when invoked. Perhaps you can start there and build up the IOrderFactory if you find you need more parameters or control?

Chris Tavares
  • 29,165
  • 4
  • 46
  • 63