问题描述
条件解析是我目前不明白的最后一件事.
假设我们有一个接口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屋!
更多推荐
[db:关键词]
发布评论