如何避免ServiceLocator反模式?

时间:2014-04-11 19:37:57

标签: dependency-injection ninject desktop-application impersonation service-locator

为了访问底层数据源,我需要提供我之前没有的当前用户凭据。

因此,为了向数据访问层提供适当的当前用户凭据,我建议我ConfigurationProvider依赖于ICurrentUser InSingletonScope()的实例ICurrentUser 3}}

我理解它的方式,我将确保对用户进行身份验证,然后绑定我的ServiceLocator,并绑定我的数据访问层的其余部分。

由于身份验证发生在我的主MDI表单中,我能看到实现它的唯一方法是将Ninject内核注入我的MDI表单的构造函数。

我关心的事实是,我看到它的方式,有必要依赖于Ninject内核本身,这绝对是不可能的,因为如果我没有弄错的话就会这样,就像使用ServiceLocator反模式。

那么,在这种情况下,如何避免{{1}}反模式?

1 个答案:

答案 0 :(得分:2)

威尔

您无需在身份验证表单中访问IResolutionRoot。配置完毕。我想出了一个示例实现,它使用注入表单的IAuthenticationService。用户输入后,您可以调用SignIn(),它将更改当前凭据实例。

从那时起,每当需要IDatabaseUserCredentials的类将接收此实例而不是默认实例时。

我还让ConfigurationProvider收到IConnectionStringProvider而不是string。查看complete gist以获取完整的示例。

public class AuthenticationService : IAuthenticationService
{
    public void SignIn(string dbInstance, string login, string password)
    {
        var user = new DatabaseUserCredentials(dbInstance, login, password);

        // A single point to manipulate your singleton instance
        DatabaseUserCredentials.Current = user;
    }
}

绑定:

public override void Load()
{
    Bind<Configuration>().ToProvider<ConfigurationProvider>();

    Bind<IAuthenticationService>().To<AuthenticationService>();

    Bind<IConnectionStringProvider>().To<ConnectionStringProvider>();

    //Use Current user if available. If not, use default credentials.
    Bind<IDatabaseUserCredentials>().ToMethod(c => DatabaseUserCredentials.Current ?? DatabaseUserCredentials.Default);
}