Ninject Get<T> WhenTargetHas<T>

752 Views Asked by At

So I'm using Ninject, specifically the contextual binding as follows :

Bind<IBlah>().ToMethod(x => FirstBlahProvider.Instance.GiveMeOne()).WhenTargetHas<FirstAttribute>().InRequestScope();
Bind<IBlah>().ToMethod(x => SecondBlahProvider.Instance.GiveMeOne()).WhenTargetHas<SecondAttribute>().InRequestScope();

I need to use the Kernel to get a given instance and would like to do it based on the Condition WhenTargetHas<T>. Something like the following would be great.

var myblah = Kernal.Get<IBlah>(x => x.HasWithTarget<FirstAttribute>)

How can you retrieve an instance based on the condition?

1

There are 1 best solutions below

0
On

Worked out the answer : Best to avoid using WhenTargetHas<T> instead use WithMetaData(key, value)

So

Bind<IBlah>().ToMethod(x => FirstBlahProvider.Instance.GiveMeOne()).WhenTargetHas<FirstAttribute>().InRequestScope();
Bind<IBlah>().ToMethod(x => SecondBlahProvider.Instance.GiveMeOne()).WhenTargetHas<SecondAttribute>().InRequestScope();

Becomes :

 Bind<IBlah>().ToMethod(x => FirstBlahProvider.Instance.GiveMeOne()).WithMetaData("Provider", "First);
 Bind<IBlah>().ToMethod(x => SecondBlahProvider.Instance.GiveMeOne()).WithMetaData("Provider", "Second");

You then need to create an Attribute which inherits the Ninject ConstraintAttribute and use that attribute in your constructor arguement.

As :

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)]
    public class FirstProviderConstraint : ConstraintAttribute
    {
             public override bool Matches(IBindingMetadata metadata)
             {
                return metadata.Has("Provider") && metadata.Get<string>("Provider") == "First"; 
             }
    }

You then use it in a constructor arg as :

public class Consumer([FirstProviderConstraint] IBlah) 
{
...
}

Or resolving from the Kernel

Get<ISession>(metaData => metaData.Get<string>(BindingKeys.Database) == BindingValues.OperationsDatabase)

I need to resolve scoping but that's how you satisfy both Constructor injection and explicit resolution from the Kernel when you have more than one binding.