Can't get value of Ninject ConstructorArgument (passed in as parameter to kernel.Get)

有些话、适合烂在心里 提交于 2019-12-02 09:48:57

Edit: After your comments and edits, I've reformulated the answer. The suggestion below is just one way to go about this. I'm implementing a Provider<ObjectContextFactory> that will inspect the parameter sent to the request when using kernel.Get<ObjectContextFactory>(). This parameter has nothing to do with constructor, it is only used as a "context variable" so you can decide what to do with it.

Here is the code:

public class ObjectContextFactory
{
    private readonly string _idNum;
    private readonly IResolutionRoot _container;

    public ObjectContextFactory(IResolutionRoot container, string idNum)
    {
        _container = container;
        _idNum = idNum;
    }

    public ObjectContext CreateObjectContext()
    {
        //Use _idNum here as you wish, here is a sample implementation
        ConstructorArgument constructorArgument;
        if (_idNum.Substring(0,1) == "2")
        {
            constructorArgument = new ConstructorArgument("connectionString", "your conn string 1");
        }
        else
        {
            constructorArgument = new ConstructorArgument("connectionString", "your conn string 2");
        }

        return _container.Get<ObjectContext>(constructorArgument);
    }
}

public class ObjectContextFactoryProvider : Provider<ObjectContextFactory>
{
    protected override ObjectContextFactory CreateInstance(IContext context)
    {
        var idNum = context.Parameters.FirstOrDefault(p => p.Name == "idNum");
        var idNumValue = idNum.GetValue(context, null) as string;

        var factory = new ObjectContextFactory(context.Kernel, idNumValue);
        return factory;
    }
}

And the bindings:

public override void Load()
{
    Bind<DBProviderBase>().To<DBProviderB>();
    Bind<ObjectContextFactory>().ToProvider<ObjectContextFactoryProvider>();
}

When retrieving the factory:

var factory = kernel.Get<ObjectContextFactory>(new Parameter("idNum", "1", true));

Another way to achieve this would be via Named Bindings. Just do a kind of translator from your idNum to a string (or use it directly) and call it when getting an instance.

I needed to use ToMethod() to get access to the appropriate context.

Bind<DBProviderBase>().ToMethod(
    ctx => {
        var idNum = ctx.Parameters.First(p => p.Name == "idNum")
            .GetValue(ctx, null) as string
        ;

        if (idNum == 2) {
            return new DBProviderB(new EF_DBEntities(
                ConfigurationManager.ConnectionStrings["EF_DB_b_conn1"]
            .ToString()));
        } else {
            return new DBProviderB(new EF_DBEntities(
                ConfigurationManager.ConnectionStrings["EF_DB_b_conn2"]
            .ToString()));
        }
    };
);

//later...
var db = kernel.Get<DBProviderBase>(
    new Ninject.Parameters.Parameter("idNum", idNum, true)
);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!