dependency injection统一 – 条件解析

有条件的解决是我目前还不了解的最后一件事。

让我们说我们有一个接口IAuthenticate

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

现在我有两种类型的身份validation。

Twitter认证

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

Facebook Auth

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

在unity配置中注册类型:

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

在我们的控制器中通过DI注入对象:

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

团结如何知道它必须为不同类型的身份validation解决哪个对象? 在这种情况下如何进行条件解决?

我和我的朋友谈过,他解释说如果这种情况出现是错误的设计,但这只是工厂模式使用的。

解决此问题的一种简单方法是使用策略模式 。 请注意,您可以在不更改设计的情况下添加或删除登录提供程序 – 您只需更改DI配置即可。

接口

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

validation提供商

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

战略

 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(string providerName, string user, string 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); } } 

团结注册

 // Note that the strings used here for instance names have nothing // to do with the strings 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") ) )); 

用法

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

团结不会没有你的帮助。 您可以在注册IAuthenticate类型时提供名称:

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

您将不再希望将IAuthenticate实例直接注入AuthenticateController。 你可以根据一个条件(服务定位器样式)得到你想要的实例:

 myContainer.Resolve("Twitter"); 

或者你会注入一个为你做这个的工厂(如果你喜欢严格的DI风格)。