依赖注入 Unity - 条件解析 [英] Dependency Injection Unity - Conditional Resolving

查看:15
本文介绍了依赖注入 Unity - 条件解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

条件解析是我目前不明白的最后一件事.

假设我们有一个接口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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆