45 votes

IoC.Resolve vs Constructor Injection

J'ai entendu beaucoup de gens dire que c'était une mauvaise pratique d'utiliser IoC.Resolve (), mais je n'ai jamais entendu pourquoi. (Si tout est une question de test, vous pouvez simplement vous moquer du conteneur et vous avez terminé).

Maintenant, les avantages d'utiliser Resolve au lieu de Constructor Injection sont que vous n'avez pas besoin de créer des classes qui ont 5 paramètres dans le constructeur, et lorsque vous allez créer une instance de cette classe, vous n'aurez plus besoin de la fournir. n'importe quoi

51voto

Bryan Watts Points 22810

IoC.Resolve<> est un exemple de Service Locator modèle. Ce modèle impose quelques restrictions que constructeur d'injection n'est pas:

  • Les objets peuvent pas avoir plus fine contexte que le domaine d'application, en raison de la statique des appels
  • Les objets de décider laquelle des versions des dépendances à résoudre. Toutes les instances d'une classe obtiendrez la même dépendance de configuration.
  • La tentation de couple de code pour le conteneur est élevé, par exemple, au lieu de créer une intention-révélatrice de l'usine.
  • Unité de test nécessite la configuration du conteneur, où les classes pourrait juste être créé et utilisé autrement. (Ceci est particulièrement gênant lorsque vous voulez tester plusieurs configurations de la même classe, en raison de la deuxième question ci-dessus.)
  • Une application de la structure ne peut pas être déduit de son API publique. (Paramètres du constructeur sont une bonne chose. Ils ne sont pas un problème, vous devriez vous sentir la nécessité de résoudre.)

Ces limitations, dans mon esprit, de reléguer le Service Locator modèle à mi-chemin entre la grand-ballon-de-la boue et l'injection de dépendance: utile si vous devez l'utiliser, mais de loin pas le meilleur choix.

26voto

Krzysztof Kozmic Points 19262

Si vous créez des classes qui ont 5 dépendances, vous avez des problèmes autres que le Cio.Résoudre.

Tirant les dépendances (plutôt que de les avoir poussés par le constructeur) complètement à côté du point de l'utilisation du Cio cadre. Vous souhaitez inverser les dépendances. Pas vos classes dépendent du Cio cadre, mais dans l'autre sens.

Si vous n'avez pas besoin de toutes les dépendances dans certains scénarios, que peut-être vous devez diviser votre classe, ou qui ont des dépendances rendu facultatif par leur propriété dépendances.


Vos classes dépendent du conteneur. Ils ne fonctionnent pas si vous les fournir avec un. Si c'est un vrai ou un faux, n'a pas d'importance. Ils sont intrinsèquement liés à l'conteneur via statique de la dépendance. Cela impose un travail supplémentaire pour vous de faire quelque chose avec vos classes. Tout moment vous souhaitez utiliser votre classe, vous devez faire glisser le conteneur avec eux. Pour aucun avantage! Service locator est juste un sac de tout ce qui est contre probablement tous les principes de la programmation orientée objet.

7voto

Grant Palin Points 3459

Cio.Résoudre est essentiellement le Service de patron de localisation. Il a sa place, mais n'est pas l'idéal. Constructeur d'injection est préféré à partir d'un point de vue de l'architecture, en tant que dépendances sont plus explicites, alors que le SL cache les dépendances au sein d'une classe. Cela réduit la capacité de test, et rend le processus plus complexe qu'elle doit être.

Si je peux me permettre, je vous suggère de lire mon récent de la série sur les techniques pour réduire le code de couplage, qui couvre SL -, DI -, et de la Coi.

3voto

orip Points 28225

L'un des avantages est qu'avec l'injection de constructeur, toutes les dépendances de classe sont visibles dès le départ.

Avec .Resolve vous devez lire le code uniquement pour comprendre les dépendances.

1voto

Chris Marisic Points 11495

Je dois souligner qu'il n'est pas forcément du mal à sauter le constructeur de l'injection et de l'utilisation statique d'injection. Il y a de grandes applications de cela, l'exemple le plus concret est de l'utiliser dans un modèle de Fabrique de la mise en œuvre.

public static class ValidationFactory
{
    public static Result Validate<T>(T obj)
    {
        try
        {
            var validator = ObjectFactory.GetInstance<IValidator<T>>();
            return validator.Validate(obj);
        }
        catch (Exception ex)
        {
            var result = ex.ToResult();
            ...
            return result;
        }
    }    
}

- Je l'utiliser avec StructureMap à gérer ma couche de validation.

Edit: un Autre exemple, j'ai de l'utilisation du container directement est de faire de certains de vos objets de domaine être singletons, sans pour autant rendre les classes statiques et l'introduction de toutes les wierdness que les classes statiques faire.

Dans certains de mes points de vue j'ai le fil jusqu'certaines entités de ce genre. Normalement, je devrais nous un Enum avec une Description de l'attribut de me donner 3 choix de valeur, mais la 3ème, dans ce cas, doit être une chaîne de caractères aussi et pas un int, donc j'ai créé une interface avec ces 3 propriétés et hériter de tous les objets du domaine de lui. Ensuite, j'ai mon conteneur scan de mon assemblée et enregistrer automatiquement puis de les sortir, j'ai juste

SomeObject ISomeView.GetMyObject
{
    get { return new SomeObject { EmpoweredEnumType = 
            ObjectFactory.GetNamedInstance<IEmpEnum>("TheObjectName");
        }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X