Unité d’dependency injection – Résolution conditionnelle

La résolution conditionnelle est la dernière chose que je ne comprends pas pour le moment.

Disons que nous avons une interface IAuthenticate :

 public interface IAuthenticate{ bool Login(ssortingng user, ssortingng pass); } 

Maintenant, j’ai deux types d’authentification.

Autorisation Twitter

 public class TwitterAuth : IAuthenticate { bool Login(ssortingng user, ssortingng pass) { //connect to twitter api } } 

Auth Facebook

 public class FacebookAuth: IAuthenticate { bool Login(ssortingng user, ssortingng pass) { //connect to fb api } } 

Enregistrement de types dans la configuration d’unité:

 unityContainer.RegisterType(); unityContainer.RegisterType(); 

injecter des objects via DI dans notre contrôleur:

 private readonly IAuthenticate _authenticate; public AuthenticateController(IAuthenticate authenticate) { _authenticate = authenticate; } // login with twitter public virtual ActionResult Twitter(ssortingng user, ssortingng pass) { bool success = _authenticate.Login(user, pass); } // login with fb public virtual ActionResult Facebook(ssortingng user, ssortingng pass) { bool success = _authenticate.Login(user, pass); } // login with google public virtual ActionResult Google(ssortingng user, ssortingng pass) { bool success = _authenticate.Login(user, pass); } 

Comment l’unité saura-t-elle exactement quel object doit-elle résoudre pour différents types d’authentification? Comment puis-je résoudre conditionnellement dans ce cas?

J’ai parlé avec un de mes amis, et il m’a expliqué que si cette situation semblait être une mauvaise conception, nous n’utilisons que le modèle d’usine.

Un moyen simple de résoudre ce problème consiste à utiliser le modèle de stratégie . Notez que vous pouvez append ou supprimer des fournisseurs de connexion sans modifier la conception. Il vous suffit simplement de modifier la configuration DI.

Des interfaces

 public interface IAuthenticate{ bool Login(ssortingng user, ssortingng pass); bool AppliesTo(ssortingng providerName); } public interface IAuthenticateStrategy { bool Login(ssortingng providerName, ssortingng user, ssortingng pass); } 

Authentifier les fournisseurs

 public class TwitterAuth : IAuthenticate { bool Login(ssortingng user, ssortingng pass) { //connect to twitter api } bool AppliesTo(ssortingng providerName) { // I used the type name for this example, but // note that you could use any ssortingng or other // datatype to select the correct provider. return this.GetType().Name.Equals(providerName); } } public class FacebookAuth: IAuthenticate { bool Login(ssortingng user, ssortingng pass) { //connect to fb api } bool AppliesTo(ssortingng providerName) { return this.GetType().Name.Equals(providerName); } } 

Stratégie

 public class AuthenticateStrategy: IAuthenticateStrategy { private readonly IAuthenticate[] authenticateProviders; public AuthenticateStrategy(IAuthenticate[] authenticateProviders) { if (authenticateProviders == null) throw new ArgumentNullException("authenticateProviders"); this.authenticateProviders = authenticateProviders; } public bool Login(ssortingng providerName, ssortingng user, ssortingng pass) { var provider = this.authenticateProviders .FirstOrDefault(x => x.AppliesTo(providerName)); if (provider == null) { throw new Exception("Login provider not registered"); } return provider.Login(user, pass); } } 

Enregistrement de l’unité

 // Note that the ssortingngs used here for instance names have nothing // to do with the ssortingngs used to select the instance in the strategy pattern unityContainer.RegisterType("twitterAuth"); unityContainer.RegisterType("facebookAuth"); unityContainer.RegisterType( new InjectionConstructor( new ResolvedArrayParameter( new ResolvedParameter("twitterAuth") ), new ResolvedArrayParameter( new ResolvedParameter("facebookAuth") ) )); 

Usage

 private readonly IAuthenticateStrategy _authenticateStrategy; public AuthenticateController(IAuthenticateStrategy authenticateStrategy) { if (authenticateStrategy == null) throw new ArgumentNullException("authenticateStrategy"); _authenticateStrategy = authenticateStrategy; } // login with twitter public virtual ActionResult Twitter(ssortingng user, ssortingng pass) { bool success = _authenticateStrategy.Login("TwitterAuth", user, pass); } // login with fb public virtual ActionResult Facebook(ssortingng user, ssortingng pass) { bool success = _authenticateStrategy.Login("FacebookAuth", user, pass); } 

L’unité ne sera pas sans votre aide. Vous pouvez donner un nom lorsque vous enregistrez vos types IAuthenticate:

 unityContainer.RegisterType("Twitter"); unityContainer.RegisterType("Facebook"); 

Vous ne voudrez plus injecter directement une instance IAuthenticate dans votre AuthenticateController. Vous obtiendrez l’instance souhaitée en fonction d’une condition sortant de l’unité (style de localisateur de service):

 myContainer.Resolve("Twitter"); 

ou vous allez injecter une usine qui le fait pour vous (si vous aimez un style ssortingct de DI).