依赖注入 Unity - 条件解析 [英] Dependency Injection Unity - Conditional Resolving
问题描述
条件解析是我目前不明白的最后一件事.
假设我们有一个接口IAuthenticate
:
公共接口 IAuthenticate{布尔登录(字符串用户,字符串传递);}
现在我有两种类型的身份验证.
Twitter 身份验证
公共类 TwitterAuth : IAuthenticate{bool 登录(字符串用户,字符串传递){//连接到推特api}}
Facebook 身份验证
公共类FacebookAuth:IAuthenticate{bool 登录(字符串用户,字符串传递){//连接到fb api}}
在统一配置中注册类型:
unityContainer.RegisterType();unityContainer.RegisterType();
通过 DI 在我们的控制器中注入对象:
private readonly IAuthenticate _authenticate;公共 AuthenticateController(IAuthenticate 验证){_authenticate = 认证;}//用推特登录公共虚拟 ActionResult Twitter(字符串用户,字符串传递){布尔成功 =_authenticate.Login(user, pass);}//使用 fb 登录公共虚拟 ActionResult Facebook(字符串用户,字符串传递){布尔成功 =_authenticate.Login(user, pass);}//用谷歌登录公共虚拟 ActionResult 谷歌(字符串用户,字符串传递){布尔成功 =_authenticate.Login(user, pass);}
unity 究竟如何知道它必须为不同类型的身份验证解析哪个对象?在这种情况下,我如何进行条件解析?
我和我的朋友谈过,他解释说如果出现这种情况是设计错误,但这只是使用的工厂模式.
解决这个问题的一个简单方法是使用 策略模式.请注意,您可以在不更改设计的情况下添加或删除登录提供程序 - 您只需更改 DI 配置.
接口
公共接口 IAuthenticate{布尔登录(字符串用户,字符串传递);bool ApplyTo(string providerName);}公共接口 IAuthenticateStrategy{bool Login(string providerName, string user, string pass);}
验证提供者
公共类 TwitterAuth : IAuthenticate{bool 登录(字符串用户,字符串传递){//连接到推特api}bool ApplyTo(string providerName){//我在这个例子中使用了类型名称,但是//请注意,您可以使用任何字符串或其他//数据类型以选择正确的提供者.返回 this.GetType().Name.Equals(providerName);}}公共类 FacebookAuth:IAuthenticate{bool 登录(字符串用户,字符串传递){//连接到fb api}bool ApplyTo(string providerName){返回 this.GetType().Name.Equals(providerName);}}
战略
公共类AuthenticateStrategy:IAuthenticateStrategy{私有只读 IAuthenticate[] authenticateProviders;公共 AuthenticateStrategy(IAuthenticate[] authenticateProviders){如果(authenticateProviders == null)throw new ArgumentNullException(authenticateProviders");this.authenticateProviders = authenticationProviders;}public bool Login(string providerName, string user, string pass){var provider = this.authenticateProviders.FirstOrDefault(x => x.AppliesTo(providerName));如果(提供者 == 空){throw new Exception(登录提供者未注册");}返回 provider.Login(user, pass);}}
统一注册
//注意这里用于实例名称的字符串没有任何内容//处理用于在策略模式中选择实例的字符串unityContainer.RegisterType<IAuthenticate, TwitterAuth>(twitterAuth");unityContainer.RegisterType<IAuthenticate, FacebookAuth>(facebookAuth");unityContainer.RegisterType(新的注入构造函数(new ResolvedArrayParameter(new ResolvedParameter<IAuthenticate>(twitterAuth"),new ResolvedParameter<IAuthenticate>(facebookAuth"))));
用法
private readonly IAuthenticateStrategy _authenticateStrategy;公共 AuthenticateController(IAuthenticateStrategy authenticateStrategy){if (authenticateStrategy == null)throw new ArgumentNullException(authenticateStrategy");_authenticateStrategy = authenticationStrategy;}//用推特登录公共虚拟 ActionResult Twitter(字符串用户,字符串传递){布尔成功 =_authenticateStrategy.Login(TwitterAuth",用户,通过);}//使用 fb 登录公共虚拟 ActionResult Facebook(字符串用户,字符串传递){布尔成功 =_authenticateStrategy.Login(FacebookAuth",用户,通过);}
unity.config
<块引用>代替统一注册"您可以在您的 unity.config 上执行此操作
Conditional resolving is the last thing I don't understand at the moment.
Lets say we have an interface IAuthenticate
:
public interface IAuthenticate{
bool Login(string user, string pass);
}
Now I have two types of authentication.
Twitter auth
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
}
}
Registering types in unity config:
unityContainer.RegisterType<IAuthenticate, TwitterAuth>();
unityContainer.RegisterType<IAuthenticate, FacebookAuth>();
inject objects via DI in our controller:
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);
}
How exactly will unity know which object does it have to resolve for different types of authentication? How do I do conditional resolving in this case?
I spoke with friend of mine, and he explained if this situation appears it is wrong design, but this is just factory pattern used.
A simple way to solve this is with the strategy pattern. Note that you can add or remove login providers without changing the design - you simply need to change the DI configuration.
Interfaces
public interface IAuthenticate{
bool Login(string user, string pass);
bool AppliesTo(string providerName);
}
public interface IAuthenticateStrategy
{
bool Login(string providerName, string user, string pass);
}
Authenticate Providers
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);
}
}
Strategy
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);
}
}
Unity Registration
// 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<IAuthenticate, TwitterAuth>("twitterAuth");
unityContainer.RegisterType<IAuthenticate, FacebookAuth>("facebookAuth");
unityContainer.RegisterType<IAuthenticateStrategy, AuthenticateStrategy>(
new InjectionConstructor(
new ResolvedArrayParameter<IAuthenticate>(
new ResolvedParameter<IAuthenticate>("twitterAuth"),
new ResolvedParameter<IAuthenticate>("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(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);
}
unity.config
Instead of "Unity Registration" you could do this on your unity.config
<register type="IAuthenticate" mapTo="TwitterAuth" name="twitterAuth" />
<register type="IAuthenticate" mapTo="FacebookAuth" name="facebookAuth" />
<register type="IAuthenticateStrategy" mapTo="AuthenticateStrategy" />
这篇关于依赖注入 Unity - 条件解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!