WinForms应用程序中的Ninject ActivationException

WinForms应用程序中的Ninject ActivationException,winforms,dependency-injection,Winforms,Dependency Injection,我正在一个项目中工作,以将DI(使用Ninject)实现到现有的WinForms应用程序中,但是我遇到了一些问题,我在WinForms中使用DI的知识充其量也有限,但是我已经在MVC项目中成功地使用了好几次 我在尝试创建具有需要存储库接口的构造函数的表单时收到以下消息: Error activating IProductionRepository No matching bindings are available, and the type is not self-bindable. Acti

我正在一个项目中工作,以将DI(使用Ninject)实现到现有的WinForms应用程序中,但是我遇到了一些问题,我在WinForms中使用DI的知识充其量也有限,但是我已经在MVC项目中成功地使用了好几次

我在尝试创建具有需要存储库接口的构造函数的表单时收到以下消息:

Error activating IProductionRepository
No matching bindings are available, and the type is not self-bindable.
Activation path:
  2) Injection of dependency IProductionRepository into parameter 
     productionRepository of constructor of type Main
  1) Request for Main
我在网上搜索过,但是我读到的关于这个错误的大部分文章要么是关于更复杂的设置,要么是关于参数注入的,我不确定这是不是这里的问题

我有一个表单,用于启动使用DI的表单(错误发生在
内核上。Get
调用:

Private Sub txt_Click(sender As System.Object, e As System.EventArgs) Handles txt.Click

    Try
        Dim kernel As Ninject.IKernel = 
            New Ninject.StandardKernel(New NinjectFactory())
        Dim form As Main = kernel.Get(Of Main)() 
        form.ConnectionString = App.pstrConnectString
        form.ShowDialog(Me)
    Catch ex As Exception
        Support.ErrorHandler.ReportError(ex.Message, ex, True)
    End Try

End Sub
我的NinjectFactory具有正确的绑定(以及其他几种已注释掉的尝试):

这就是我以前在MVC项目中使用Ninject的方式,我没有遇到任何问题,但是很明显WinForms有一些不同之处


任何帮助都将不胜感激。

我建议使用单点依赖解析,即Mark Seemann(@Mark Seemann)在其伟大的著作《.NET中的依赖注入》中建议的
合成根
。你的合成根可能如下所示:

public class CompositionRoot
{
    private static IKernel _ninjectKernel;

    public static void Wire(INinjectModule module)
    {
        _ninjectKernel = new StandardKernel(module);
    }

    public static T Resolve<T>()
    {
        return _ninjectKernel.Get<T>();
    }
}

public class ApplicationModule : NinjectModule
{
    public override void Load()
    {
        Bind(typeof(IRepository<>)).To(typeof(GenericRepository<>));
    }
}
private void button1_Click(object sender, EventArgs e)
{
    MessageBox.Show(_productionRepository.ToString());
}
现在,您的按钮处理程序可以如下所示:

public class CompositionRoot
{
    private static IKernel _ninjectKernel;

    public static void Wire(INinjectModule module)
    {
        _ninjectKernel = new StandardKernel(module);
    }

    public static T Resolve<T>()
    {
        return _ninjectKernel.Get<T>();
    }
}

public class ApplicationModule : NinjectModule
{
    public override void Load()
    {
        Bind(typeof(IRepository<>)).To(typeof(GenericRepository<>));
    }
}
private void button1_Click(object sender, EventArgs e)
{
    MessageBox.Show(_productionRepository.ToString());
}
注意:如果您想用不同的依赖项测试应用程序,可能就是这样,那么您可以创建另一个具有不同布线配置的模块。在测试中,您将有另一个带有存根和模拟的布线逻辑。 我也不喜欢模型中的NInject属性,如果你使用构造函数注入,你可以去掉它们。我的实体是简单的POCO

public interface IProductionRepository
{
}

public class ProductionRepository : IProductionRepository
{
    public override string ToString()
    {
        return "Foo";
    }
}

Mark还为使用DI模式的WinForms以及如何实现它提供了一个很好的案例,我真的建议他写这本书。

非常感谢你回答我提出的这两个与Ninject相关的问题!我感觉很快就会有另一个问题了!关于DI主题,有很多好的和复杂的问题,请随意提问)如果你想再次帮助我,我的下一个问题就是干杯!谢谢
public interface IProductionRepository
{
}

public class ProductionRepository : IProductionRepository
{
    public override string ToString()
    {
        return "Foo";
    }
}