如何当它被注入到另一个字符串对象的方法绑定?(How to bind a string to a m

2019-10-19 20:00发布

我有一个NHibernate.Cfg.Configuration提供商。

ConfigurationProvider

public class ConfigurationProvider : Provider<Configuration> {
    public class ConfigurationProvider(string connectionString
        , Assembly mappings) {
        ConnectionString = connectionString;
        Mappings = mappings;
    } 

    protected override Configuration CreateInstance(IContext context) {
        var c = new Configuration().Configure();
        c.AddAssembly(Mappings);
        c.Properties["connection.connection_string"] = ConnectionString;
        return c;
    }

    private readonly string ConnectionString;
    private readonly Assembly Mappings;
}

其连接字符串来自Configurationservice.BuildConnectionString()我的应用程序。

ConfigurationService

public class ConfigurationService {
    public ConfigurationService(ICurrentUser user) { CurrentUser = user; }

    public string BuildConnectionString() {
        return string.Format(DefaultConnectionString
            , CurrentUser.DatabaseInstanceName
            , CurrentUser.Login
            , CurrentUser.Password);
    }

    private readonly ICurrentUser CurrentUser;
}

这反过来又依赖于CurrentUser来冒充。

当前用户

public class CurrentUser : ICurrentUser {
    public CurrentUser(string dbinstance, string login, string password) { 
        DatabaseInstanceName = dbinstance;
        Login = login;
        Passwword = password;
    }

    public readonly string DatabaseInstanceName;
    public readonly string Login;
    public readonly string Password;
}

所以手动进我的依赖将如下所示:

string dbInstance = authenticationDialog.DatabaseInstanceName;
string login = authenticationDialog.Login;
string password = authenticationDialog.Password;

var nHibernateConfigurationProvider = 
    new ConfigurationProvider(
        new ConfigurationService(
            new CurrentUser(dbInstance, login, password)).BuildConnectionString()
        , Assembly.GetExecutingAssembly());

问题是,我不知道如何绑定,使用Ninject,该ConfigurationService.BuildConnectionString()方法来解决string中使用构造函数的参数ConfigurationProvider.ctor()

推进一步,我怎么告诉Ninject到实际结合这些类型只有当用户通过验证?

这里是我到目前为止

// Wait until user is authenticated before continuing to bind???
Bind<string>().ToMethod(ctx => ctx.Request.???.BuildConnectionString()).WhenInjectedInto<ConfigurationProvider>().InSingletonScope();
Bind<Assembly>().ToConstant<Assembly>(Assembly.GetExecutingAssembly().WhenInjectedInto<ConfigurationProvider>();

Answer 1:

Here is my suggestion on how you can achieve this.

Since you don't have the data beforehand and only when your ICurrentUser is created via the credentials and parameters you need, it means that you need to "save it" into a globally accessible location once it has been created.

If we think about a web .NET application, that would tipically involve binding the ICurrentUser with InRequestScope() using a static reference to a HttpContext.

As this is not your case, I've chosen to bind ICurrentUser as a singleton and initialize it passing the values. When you need your other classes that depend on it, the container will pass the already-initialized instance, since it is bound with InSingletonScope().

I've also tried to mimic your current dependencies. For instance, instead of passing in the connectionString to ConfigurationProvider, my way of doing it would be declare a direct dependency on ConfigurationService in order to obtain the information.

// Do your stuff to collect credentials

// User now authenticated, initialize ICurrentUser instance singleton
// You could have used a ICurrentUserFactory or static member, this is just a sample implementation
kernel.Get<ICurrentUser>(new ConstructorArgument("dbInstance", dbInstance),
    new ConstructorArgument("login", login),
    new ConstructorArgument("password", password));

// You can now access your NHibernate configuration properly
var config = kernel.Get<Configuration>();

And the bindings:

Bind<Configuration>().ToProvider<ConfigurationProvider>();
Bind<ConfigurationProvider>()
    .ToMethod(
        ctx => new ConfigurationProvider(ctx.Kernel.Get<ConfigurationService>().BuildConnectionString()));

Bind<ICurrentUser>().To<CurrentUser>().InSingletonScope();

Hope this helps.



文章来源: How to bind a string to a method of an object when it is injected into another?