Can I specify multiple parameters using WhenInjectedInto for ninject?

1k views Asked by At

When setting up my ninject bindings, I'm using the .ToMethod to specify particular parameters for specific connectionstrings, and the WhenInjectedInto method to constrain the binding to specific types:

        Bind(Of IDbConnection).ToMethod(Function(context) New OracleConnection(ConnectionStringFactory.GetConnection(DBC.ConnectionStrings.Oracle))).WhenInjectedInto(Of AccountBalancesLookup)()
        Bind(Of IDbConnection).ToMethod(Function(context) New OracleConnection(ConnectionStringFactory.GetConnection(DBC.ConnectionStrings.Oracle))).WhenInjectedInto(Of MFUtility)()

My question is, can I do something like this:

        Bind(Of IDbConnection).ToMethod(Function(context) New OracleConnection(ConnectionStringFactory.GetConnection(DBC.ConnectionStrings.Oracle))).WhenInjectedInto(Of AccountBalancesLookup, MFUtility)()

Specifying more than one destination for the binding at once, rather than having multiple lines?

1

There are 1 answers

0
BatteryBackupUnit On BEST ANSWER

Not out of the box. But you can create your own extension to When(Func<IRequest,bool>) which does exactly that. For example:

public static class WhenExtensions
{
    public static IBindingInNamedWithOrOnSyntax<T> WhenInjectedInto<T>(
        this IBindingWhenSyntax<T> syntax, params Type[] types)
    {
        var conditions = ComputeMatchConditions(syntax, types).ToArray();
        return syntax.When(request => conditions.Any(condition => condition(request)));
    }

    private static IEnumerable<Func<IRequest, bool>> ComputeMatchConditions<T>(
        IBindingWhenSyntax<T> syntax, Type[] types)
    {
        foreach (Type type in types)
        {
            syntax.WhenInjectedInto(type);
            yield return syntax.BindingConfiguration.Condition;
        }
    }
}

used like:

public class Test
{
    [Fact]
    public void Foo()
    {
        var kernel = new StandardKernel();

        kernel.Bind<string>().ToConstant("Hello")
            .WhenInjectedInto(typeof(SomeTypeA), typeof(SomeTypeB));

        kernel.Bind<string>().ToConstant("Goodbye")
            .WhenInjectedInto<SomeTypeC>();

        kernel.Get<SomeTypeA>().S.Should().Be("Hello");
        kernel.Get<SomeTypeB>().S.Should().Be("Hello");

        kernel.Get<SomeTypeC>().S.Should().Be("Goodbye");
    }
}

public abstract class SomeType
{
    public string S { get; private set; }

    protected SomeType(string s)
    {
        S = s;
    }
}

public class SomeTypeA : SomeType
{
    public SomeTypeA(string s) : base(s) { }
}

public class SomeTypeB : SomeType
{
    public SomeTypeB(string s) : base(s) { }
}

public class SomeTypeC : SomeType
{
    public SomeTypeC(string s) : base(s) { }
}

Note that ComputeMatchConditions is kind of a hack because it relies on ninject internals.. if these (the implementation of WhenInjectedInto) change then this may stop to work. Of course you're free to provide your own alternative implementation. You could also copy the code from WhenInjectedInto, see: BindingConfigurationBuilder.cs method WhenInjectedInto(Type parent)