2012-03-12 68 views
2

当Ninject遇到多重绑定分辨率问题时,有没有办法让Ninject调用一个函数?Ninject - 拦截多重绑定分辨率

基本上,我想有这样的:

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() {} 
} 

更多背景:
我像架构的插件使用Ninject。插件可以使用一种或多种类型的连接提供者(每个连接提供者类型都有一个从IMotherConnProv继承的接口)。
目前我使用XML扩展将每个IProvideConnX映射到实现(每个IProvideConnX可以有多个实现),但用户在想要更改连接类型时编辑XML文件非常繁琐。我做了一个小应用程序,帮助他们用闪亮的按钮和一切来修改XML文件,但我觉得应该有一个更动态的方式来做到这一点(Ninject是关于从XML释放自己,对吧?)。
因此,我想使用程序集扫描程序发现所有可能的选择,并以某种方式告诉Ninject在运行时哪个绑定可供选择(取决于用户的选择)。

任何想法? (我看了一下that solution,但我看不到如何使它适应无限数量的接口和实现)

+0

以及你有什么想*当有多个'IProvideConn'配置*发生?应该绑定哪一个? – BrokenGlass 2012-03-12 14:54:21

+0

用户选择的一个。然后我可以提供一种机制来保存/恢复选择。 – Thibaut 2012-03-12 15:20:53

回答

2

不,你不能。但是,你可以配置你的绑定,这样就不会发生:

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); 
     } 
    } 
} 

,并添加IConnectionType为每个连接指定nessary信息让用户选择它。

https://github.com/ninject/ninject.extensions.conventions/wiki/What-is-configuration-by-conventions

+0

看起来非常好!但我不明白如何使用它,kernel.Bind似乎不接受委托(我使用ninject 2.2和约定扩展)。 我看了一下在约定扩展中的单元测试,但在任何地方都找不到这个语法,你有其他的例子吗? – Thibaut 2012-03-13 10:10:49

+0

基本上,这不构建:使用Ninject的 ; 使用Ninject.Planning.Bindings;使用Ninject.Extensions.Conventions的 ; using System.Reflection; 类节目 { 静态无效的主要(字符串[]参数) { 使用(的iKernel内核=新StandardKernel()){ kernel.Bind( X => x.From(Assembly.GetExecutingAssembly()) .SelectAllTypes() .BindToDefaultInterface() .Configure((binding,componentType)=> b.When(r => true))); } } – Thibaut 2012-03-13 10:16:02

+0

这需要3.0表单NuGet(Install-Package Ninject.Extensions.Conventions -pre) – 2012-03-13 11:23:45