Question

J'ai du mal à comprendre comment utiliser IoC dans un scénario où je dois créer des objets de manière dynamique. Supposons que j'ai ce cours:

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'un ICommandStack, mais pas les entités. Ils ne reçoivent que 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 supérieur à 10 pour les entités individuelles. Je ne veux pas créer de constructeurs avec autant de paramètres.

Mon idée était donc de remettre une FieldFactory aux entités:

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

Au moins, la commande ICommandStack (pour Entity), désormais inutile, est maintenant partie Mais comment la FieldFactory crée-t-elle un champ? ICommandStack peut uniquement être injecté - mais la création de Fields doit encore être effectuée à l'aide du 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?

Était-ce utile?

La solution

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

Sinon, les tortues sont tout en bas. Vous avez besoin d’un objet pour demander au conteneur une nouvelle instance à un moment donné. Si vous souhaitez que vos champs soient DI-injectés, vous devez demander au conteneur de les construire ou de les construire.

Donc, pour résumer, j'irais avec l'usine.

Autres conseils

Au printemps (et Spring.NET), il existe un concept de "portée prototype". haricot / objet.

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 de les relier tous ensemble, un prototype d'étendue créera une nouvelle instance de l'objet à tout moment demandé par le conteneur IoC. Je ne sais pas quel cadre de DI vous utilisez, mais il pourrait avoir quelque chose de similaire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top