Thursday, May 5, 2011

IoC: How to create objects dynamically

Hello,

I have a problem to understand how to use IoC in a scenario where I need to create objects dynamically. Lets assume I have this classes:

abstract class Field {
  public Field( ICommandStack commandStack ) {}
}

abstract class Entity {
  public readonly Collection<Field> Fields { get; }
}

class EntityA {
  public EntityA( ICommandStack commandStack ) {
    Fields.Add( new StringField( commandStack ) );
  }
}

class EntitiyB {
  public EntityB( ICommandStack commandStack ) {
    Fields.Add( new IntField( commandStack ) );
    Fields.Add( new IntField( commandStack ) );
    Fields.Add( new IntField( commandStack ) );
  }
}

So my problem is the creation of Fields in the constructors. My Fields need an ICommandStack, but the Entities do not. They only get the ICommandStack for the creation of their Fields.

It could be easier to request the Fields as an argument in each Entity's constructor. But the number of Fields could be >10 for single Entities. I don't want to create constructors with so many parameters.

So my idea was to hand over a FieldFactory to the Entites:

class EntityA {
  public EntityA( IFieldFactory fieldFactory ) {
    // create as many fields as needed via the factory
    Fields.Add( fieldFactory.CreateStringField() );
  }
}

At least the (for Entity) unneccessary ICommandStack is now gone. But how does the FieldFactory create a Field? It only can get the ICommandStack injected - but the creation of Fields has still to be done via the 'new' keyword. Or should I give the factory a reference to my DI-container?

What is a good design solution here?

From stackoverflow
  • In Spring (and Spring.NET) there is the concept of a "prototype-scoped" bean/object.

    http://static.springframework.org/spring/docs/2.0.x/reference/beans.html#beans-factory-scopes-prototype

    Rather than injecting fixed objects and wiring them all together, a prototype scope will create a new instance of the object anytime it's requested from the IoC container. I'm not sure what DI framework you're using, but it might have something similar.

    tanascius : But where and how do I request? The FieldFactory still needs a reference to the container to request the objects.
  • I'd use a FieldFactory and inject the factory with a reference to the container (or to an interface that abstracts it if you are not happy with taking a strong dependency on your container).

    Otherwise, it's turtles all the way down. You need some object to ask the container for a new instance at some point. If you want your fields to be DI-injected, then you need to ask the container to build them or you.

    So to summarize, I'd go with the factory.

0 comments:

Post a Comment