0

我正在开发一个将 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 的表单(kernel.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 具有正确的绑定(以及其他几个被注释掉的尝试):

public class NinjectFactory : NinjectModule
{
    private IKernel _ninjectKernel;

    public NinjectFactory()
    {
        _ninjectKernel = new StandardKernel();
    }

    public override void Load()
    {
        //_ninjectKernel.Bind(typeof(IRepository<>))
        //    .To(typeof(GenericRepository<>));
        //_ninjectKernel.Bind(typeof(IProductionRepository))
        //    .To(typeof(ProductionRepository));
        _ninjectKernel.Bind<IProductionRepository>().To<ProductionRepository>();
    }
}

最后我有了我想要启动的表格:

private IProductionRepository _productionRepository;

public string ConnectionString 
{
    get
    {
        return _connectionString;
    }
    set
    {
        _connectionString = value;
    } 

    [Inject]
    public Main(IProductionRepository productionRepository) : this()
    {   
        this._productionRepository = productionRepository;        
    }

    public Main()
    {
        InitializeComponent();
    }

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

任何帮助将不胜感激。

4

1 回答 1

2

我建议使用Composition RootMark Seemann (@mark-seemann) 在他的好书中所建议的单点依赖解析,称为Dependency Injection in .NET。您的 CompositionRoot 可能如下所示:

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

你可以把它们接线Program

CompositionRoot.Wire(new ApplicationModule());

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

Application.Run(CompositionRoot.Resolve<Form1>());

现在您的按钮处理程序可能如下所示:

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 以及如何实现它提供了一个很好的案例,我真的推荐他的书。

于 2013-01-04T12:12:15.277 回答