2009-05-04 2 views
4

J'ai un problème pour comprendre comment utiliser IoC dans un scénario où j'ai besoin de créer des objets dynamiquement. Supposons que j'ai ces classes:IoC: Comment créer des objets dynamiquement

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)); 
    } 
} 

Mon problème est donc la création de champs dans les constructeurs. Mes champs ont besoin d'une ICommandStack, mais pas les entités. Ils obtiennent seulement l'ICommandStack pour la création de leurs champs.

Il pourrait être plus facile de demander les champs en tant qu'argument dans le constructeur de chaque Entité. Mais le nombre de champs pourrait être> 10 pour des entités uniques. Je ne veux pas créer de constructeurs avec autant de paramètres.

Mon idée était donc de remettre un FieldFactory aux Entités mises:

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

Au moins (pour l'entité) unneccessary ICommandStack est maintenant disparu. Mais comment le FieldFactory crée-t-il un champ? Il ne peut qu'injecter ICommandStack - mais la création de Fields doit encore se faire via le mot clé 'new'. Ou devrais-je donner à l'usine une référence à mon conteneur DI?

Qu'est-ce qu'une bonne solution de conception ici?

Répondre

3

J'utiliserais une FieldFactory et injecterais l'usine avec une référence au conteneur (ou à une interface qui l'abstraite si vous n'êtes pas content de prendre une forte dépendance sur votre conteneur).

Sinon, c'est des tortues tout le long. Vous avez besoin d'un objet pour demander au conteneur une nouvelle instance à un moment donné. Si vous voulez que vos champs soient injectés par DI, vous devez demander au conteneur de les construire ou vous. Donc, pour résumer, j'irais avec l'usine.

0

Dans Spring (et Spring.NET), il y a le concept d'un bean/objet «prototype-scoped».

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

plutôt que d'injecter des objets fixes et les câblage tous ensemble, un champ prototype va créer une nouvelle instance de l'objet à tout moment il est demandé à partir du conteneur IoC. Je ne suis pas sûr du cadre DI que vous utilisez, mais il pourrait avoir quelque chose de similaire.

+0

Mais où et comment puis-je demander? Le FieldFactory a toujours besoin d'une référence au conteneur pour demander les objets. – tanascius