simon
simon

Reputation: 835

Binding ninject via name

I have a ninject problem where I am using the same interface on multiple types to provide a config class for my application.

The entry point classes (below) that start that application are returned from the ninject kernel and I have a named Config dependency on that class.

    public ProcessA(ILogger logger, [Named("TypeA")] IConfigProvider configProvider)
    {
        _logger = logger;
        _configProvider = configProvider;
    }

    public ProcessB(ILogger logger, [Named("TypeB")] IConfigProvider configProvider)
    {
        _logger = logger;
        _configProvider = configProvider;
    }

And then in my bindings

        Bind<IConfigProvider>().To<ProcessA>().Named("TypeA");
        Bind<IConfigProvider>().To<ProcessB>().Named("TypeB");

Further down the processing line ProcessA and ProcessB share some classes that need an IConfigProvider but when the ProcessA or ProcessB gets to that point ninject cannot resolve the dependancy. I can't make it a named dependency at that point because the classes are used by both processors.

I could pass the concrete Config class down from ProcessA and ProcessB removing the constructor dependency but that doesn't seem the right way to do it.

EDIT 1 (from BatteryBackupUnit's answer)

I removed the named references and added the below which seems to do the trick. Found a method on the following question Ninject Bind When Ancestor Of Type T but I had to add in a check for request.Target == null else it wouldnt work when I got an instance of ProcessA and ProcessB from the ninject kernel.

    public override void Load()
    {
        Bind<IConfigProvider>()
            .To<TypeAConfigProvider>()
            .When(request => HasAncestorOfType<ProcessA>(request));

        Bind<IConfigProvider>()
            .To<TypeBConfigProvider>()
            .When(request => HasAncestorOfType<ProcessB>(request));
    }

    private static bool HasAncestorOfType<T>(IRequest request)
    {
        if (request == null || request.Target == null) 
            return false;

        if (request.Target.Member.ReflectedType == typeof(T)) 
            return true;

        return HasAncestorOfType<T>(request.ParentRequest);
    }

Upvotes: 1

Views: 1686

Answers (1)

BatteryBackupUnit
BatteryBackupUnit

Reputation: 13233

You can use the contextual binding mechanism to achieve that. See IBindingWhenSyntax.cs for all available methods. How about WhenAnyAncestorNamed?

Alternatively, there's the WhenInjectedInto<> binding which would be used like:

Bind<IConfigProvider>().To<ConfigA>()
    .WhenInjectedInto<ProcessA>();

Now since you don't actually want to inject it directly into ProcessA you'd have to use a When condition like WhenInjectedIntoAncestor<Process>(). You can create this yourself - as an extension method extending from the WhenAnyAncestorMatches extension method. Also see here

Upvotes: 1

Related Questions