使用 NInject 时根据区域性切换连接字符串

Switch connection string based upon culture when using NInject

请问是否可以根据当前文化使用 Ninject 绑定切换 DbContext 的连接字符串?我目前的(非工作)鳕鱼如下。

    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

    private static string GetCultureBasedConnectionString()
    {
        string culture = "de-DE"; // TODO Replce with Thread.CurrentThread.CurrentCulture.Name
        string cultureBasedConnectionString = ConnectionStringHelper.GetConnectionStringWithCulture(culture);
        return cultureBasedConnectionString;
    }

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<ApplicationDb>().To<ApplicationDb>()
            .InRequestScope()
            .WithConstructorArgument("connectionString", context => GetCultureBasedConnectionString());
        .
        .
        .
    }

这是基于此处的示例 Ninject - dynamically specifying a connection string based on a sub domain,但它不会在每次请求时调用我的 GetCultureBasedConnectionString() 方法,除非应用程序启动时...

我在此处阅读了 So that using NInjects Rebind() method is not good.

也没有把我引向正确的方向。

使用 Func<string> 的细微变化,它回调我的 GetCultureBasedConnectionString() 方法,这似乎推迟了 GetCultureBasedConnectionString() 方法的执行,直到 HttpRequest 被创建,现在出现为我工作...这是预期的行为吗?

    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

    private static string GetCultureBasedConnectionString()
    {
        string culture = Thread.CurrentThread.CurrentCulture.Name;
        string cultureBasedConnectionString = ConnectionStringHelper.GetConnectionStringWithCulture(culture);
        return cultureBasedConnectionString;
    }

    private static Func<string> ConnectionStringGetter()
    {
        var function = new Func<string>(GetCultureBasedConnectionString); 
        return function;
    }

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<ApplicationDb>().To<ApplicationDb>()
            .InRequestScope()
            .WithConstructorArgument("connectionStringGetter", context => ConnectionStringGetter());

是的,您描述的是预期的行为。绑定代码会在……好吧,当你调用 Bind 时执行——而不是每次检索类型时。 ToMethod 中指定的 Func/Method 将在每次应用绑定时执行。

尽管我相信您可以将代码简化为:

kernel.Bind<ApplicationDb>().To<ApplicationDb>()
        .InRequestScope()
        .WithConstructorArgument(
            "connectionStringGetter",
            context => GetCultureBasedConnectionString());

从而摆脱 ConnectionStringGetter().