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风格)。
- 无法加载文件或程序集’EntityFramework,Version = 6.0.0.0,
- 如何在ASP .NET MVC 5中为AspNetUser创建SecurityStamp
- 如何使用存储过程插入数据表时获取范围标识列
- 当我尝试保存新记录或更新现有记录时,EF将0000-0000-0000-xxx作为Guid返回?
- 在没有公共建设者的情况下模拟密封课程?
- 打印从WebBrowser控件在设置默认值后打印到错误的打印机
- 用C#写我的第一个DSL,然后挂上func &Action
- 如何将24小时格式的TimeSpan转换为12小时格式的TimeSpan?
- 使用x86但不是x64的Console.Writeline