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.