Reputation: 21
Is there a way to have Ninject call a function when it has trouble with multiple binding resolution ?
Basically, I would like to have this:
static void Main(string[] args)
{
StandardKernel k = new StandardKernel();
k.Bind<IProvideConn>().To<probe1>(); // these bindings are actually done by assembly scanner, I don't know how many types are available
k.Bind<IProvideConn>().To<probe2>();
k.Bind<plugin1>().ToSelf();
k.Get<plugin1>(); // Currently throws a "multiple bindings registered" exception
//but I would like it to call solveMyIssues.sortThingsOut
}
public class solveMyIssues
{
public IBinding sortThingsOut(IEnumerable<IBinding> availableBindingsForThisResolve)
{
int i = AskChoiceFromUser(availableBindingsForThisResolve);
return availableBindingsForThisResolve[i];
}
}
interface IProvideConn0
{
void goCrazy();
}
public class plugin1
{
public void talkWithUser(IProvideConn0 pc)
{
pc.goCrazy();
}
}
public class probe1 : IProvideConn0
{
public void goCrazy() {}
}
public class probe2 : IProvideConn0
{
public void goCrazy() {}
}
More context:
I'm using Ninject in a plugin like architecture. Plugins can use one or more types of connection providers (each connection provider type has an interface that inherits from IMotherConnProv).
Currently I use the XML extension to map each IProvideConnX to an implementation (each IProvideConnX can have several implementations), but it's quite tedious for users to edit XML files when they want to change connection types.
I made a small application that helps them modify the XML file with shiny buttons and everything, but I feel like there should be a more dynamic way to do that (Ninject is about freeing myself from XML, right ?).
So I would like to use the assembly scanner to discover all possible choices, and somehow tell Ninject at runtime which binding to choose from (depending on user choice).
Any ideas ? (I had a look at that solution but I can't see how to adapt it to an indefinite number of interfaces and implementations)
Upvotes: 2
Views: 729
Reputation: 32725
No you can't. But you can configure your bindings so that it won't happen:
kernel.Bind(
x => x.FromThisAssembly()
.SelectAllClasses().InheritedFrom<IProvideConn0>()
.BindToAllInterfaces()
.Configure((binding, componentType) => b.When(r => kernel.Get<IConfiguration>().ConnectionType == componentType.Name)));
kernel.Bind(
x => x.FromThisAssembly()
.SelectAllClasses().InheritedFrom<IConnectionType>()
.BindToAllInterfaces();
public class Configuration : IConfiguration
{
public Configuration(IEnumerable<IConnectionType> connectionTypes) { ... }
public string ConnectionType
{
get
{
return this.UserWhichConnectionDoYouWant(connectionTypes);
}
}
}
and add a IConnectionType for each connection specifying the nessary information to let the user select it.
See https://github.com/ninject/ninject.extensions.conventions/wiki/What-is-configuration-by-conventions
Upvotes: 2