【问题标题】:Bind generic Interface in Ninject在 Ninject 中绑定泛型接口
【发布时间】:2012-08-19 04:43:43
【问题描述】:

所以,我挖了很长时间才找到答案,但没有运气。

我做错了什么?

Ninject 抛出异常并显示此消息:

Error activating IModelRepository{User}

No matching bindings are available, and the type is not self-bindable.


这是我的代码:

我有一个通用接口:

public interface IModelRepository<T> where T: IModel
{
    //interface stuff here
}


具体的类是:

public UserRepository : IModelRepository<User>
{
    public UserRepository(IDocumentStore documentStore, string databaseName)
    {
        //constructor code here
    }
}


Ninject 模块 Load():

public override void Load()
{
    string databaseName = Properties.Settings.Default.DefaultDatabaseName;

    Bind<IModelRepository<User>>()
        .To<UserRepository>()
        .WithConstructorArgument("documentStore", Kernel.Get<IDocumentStore>())
        .WithConstructorArgument("databaseName", databaseName);
}


Ninject 实例化(这是发生异常的地方):

Kernel = new Ninject.StandardKernel(new DIModules.ModelRepositoryModule()
                                   ,new DIModules.DocumentStoreModule());

这是完整的堆栈跟踪:

at Ninject.KernelBase.Resolve(IRequest request) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 359
at Ninject.ResolutionExtensions.GetResolutionIterator(IResolutionRoot root, Type service, Func`2 constraint, IEnumerable`1 parameters, Boolean isOptional, Boolean isUnique) in c:\Projects\Ninject\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:line 263
at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters) in c:\Projects\Ninject\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:line 37
at xl.view.DIModules.DataStoreModule.Load() in c:\Users\Michael\Google Drive\Projects\Windows\xl\xl.view\DIModules\DataStoreModule.cs:line 18
at Ninject.Modules.NinjectModule.OnLoad(IKernel kernel) in c:\Projects\Ninject\ninject\src\Ninject\Modules\NinjectModule.cs:line 85
at Ninject.KernelBase.Load(IEnumerable`1 m) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 217
at Ninject.KernelBase..ctor(IComponentContainer components, INinjectSettings settings, INinjectModule[] modules) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 100
at Ninject.KernelBase..ctor(INinjectModule[] modules) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 57
at Ninject.StandardKernel..ctor(INinjectModule[] modules) in c:\Projects\Ninject\ninject\src\Ninject\StandardKernel.cs:line 46
at xl.view.Program.InitializeApplication() in c:\Projects\Windows\xl\xl.view\Program.cs:line 53
at xl.view.Program.Main() in c:\Windows\xl\xl.view\Program.cs:line 28

【问题讨论】:

    标签: ninject


    【解决方案1】:
     .WithConstructorArgument("documentStore", Kernel.Get<IDocumentStore>())
    

    您可能希望将其更改为 ctx=&gt; Kernel.Get&lt;IDocumentStore&gt;()。按照您的称呼方式,您是在模块 Load() 期间创建对象 - 这不应该是这种情况 - 模块 Load() 方法应该只有 Bind() 的东西。

    此外,手头没有开发环境,但很确定应该有一种方法让默认配置负责将该 ctor 参数绑定到任何 DI 将解决的问题。

    (如果以上都没有意义,您肯定需要提供比您拥有的更完整的堆栈跟踪)

    【讨论】:

    • 我是 Ninject 的新手(通常是 DI),所以我不确定如何克服构造函数中对该对象的需求。我将如何在那里注入 IDocumentStore?我在原始帖子中添加了堆栈跟踪。
    • 我刚刚注意到您的 Lambda 表达式 (ctx=>)。你是说这就是我应该在那里注入 IDocumentStore 的方式吗?我会试试这个。谢谢。
    • @mpalmer78 是的,lambda arg 将它从您在模块加载期间完成单个解决方案转变为使用将导致每个解决方案创建适当的文档实例重载的重载。 (即使您确实想要共享实例,您也应该通过确定 IDocumentStore 的范围来实现),您的堆栈跟踪强烈支持我关于您出错的理论。 (并且 +1 现在是一个可以回答的正确问题)
    • 我终于有时间尝试一下,这绝对是问题所在。我不再收到异常,并且 Ninject 能够正确绑定和注入。非常感谢您的帮助。
    • @mpalmer78 很高兴您对 * 的友好和专业使用得到了排序和公平竞争 - 很高兴知道最后发生了什么。
    【解决方案2】:

    尝试更改模块的顺序,似乎顺序很重要,因为IModelRepository&lt;User&gt; 在绑定它们之前不知道IModelUser

    Kernel = new Ninject.StandardKernel(
        new DIModules.DocumentStoreModule(),
        new DIModules.ModelRepositoryModule());
    

    这对我来说很有效,这里是完整的示例:http://pastebin.com/2TjBqAwc

    【讨论】:

    • 我已更改代码中的模块顺序并得到相同的异常。将您在 pastebin 上的代码(感谢 BTW)与我的代码进行比较,我看不出哪里出错了。它几乎完全相同。当我今晚有更多时间时,我将在我的项目中连接 Ninject 源代码并逐步查看我是否能注意到我的错误。
    • 您是否尝试将Bind&lt;User&gt;().ToSelf() 添加到您的public override void Load() 实现中?
    • 感谢您指出这一点...这帮助我了解了一些关于如何实例化我的模型对象(如 User. Bind.ToSelf() 现在对我来说很有意义。谢谢。