首页 文章

使用Ninject和Entity Framework在WinForms中进行依赖注入

提问于
浏览
17

我目前正在开发一个项目,我们将旧的DataSet,存储过程WinForm应用程序转换为使用实体框架,以便新网站可以访问相同的对象模型和存储库 .

无论如何,我正在尝试在表单中实现依赖注入,以便我们可以使用模拟的存储库进行单元测试 . 我使用Ninject的原因很简单,我之前在MVC网站中使用过Ninject,但是在WinForm应用程序中尝试实现这一点,至少可以证明是有问题的,因为在WinForms中缺乏有关DI的信息而更加困难 . 网络 .

到目前为止,我已经创建了Ninject Factory和存储库,但是我没有太多运气将存储库注入表单中 .

因此,有人可以帮助我或提出任何建议吗?

下面我的部分代码可能有所帮助:

Ninject工厂:

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

带有存储库的表单:

Public Class TaskForm
    Inherits BaseBusinessDialogForm

    Private _repository As TaskRepository
    Private _task As Production.Task = Nothing

    Public Sub New(ByVal task As Production.Task)

        InitializeComponent()

        _repository = New TaskRepository(ConnectString)

        If task.TaskID = 0 Then
            _task = task
        Else
            _task = _repository.GetByID(task.TaskID)
        End If

        MyBase.BusinessObject = _task
        Me.TaskBindingSource.DataSource = MyBase.BusinessObject

    End Sub

启动包含上述表单的MDI表单的类:

Dim kernel As IKernel = New StandardKernel(New NinjectFactory())
''Dim kernel As IKernel = New StandardKernel(New NinjectFactoryTest())
mfrmMDI = kernel.Get(Of Forms.MDI)()

Application.DoEvents()
mfrmMDI.ShowDialog()

我知道我的问题有点模糊,但我不确定问题在哪里或我需要完成什么 .

非常感谢

1 回答

  • 35

    您可以将组合根创建为解决方案的一个入口点 . 您将INjectModule作为参数传递,以便您可以配置它以不同方式进行测试 . Composition Root的一个好处是,并非所有程序集都依赖于NInject,并且您将只有一个单点来更改分辨率逻辑 . 这可能是一个很酷的模式,你可能会在未来更改IoC容器或引入一些动态拦截 .

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

    在main方法中,您将 ApplicationModule 作为参数传递并解析 Form1 并启动它 .

    [STAThread]
    static void Main()
    {
        CompositionRoot.Wire(new ApplicationModule());
    
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
    
        Application.Run(CompositionRoot.Resolve<Form1>());
    }
    

    Form1 构造函数中,您使用特定的已关闭通用参数传递所需的存储库

    public partial class Form1 : Form
    {
        private IRepository<Process> _processRepository;
    
        public Form1(IRepository<Process> productionRepository)
        {
            this._processRepository = productionRepository;        
            InitializeComponent();
        }  
    
        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show(_processRepository.ToString());
        }
    }
    

    您的存储库可能非常复杂,但我不会向它们添加任何功能,而不是 ToString() 方法,以便我们可以看到依赖项是否已正确解析 . 请注意,存储库中没有任何属性 .

    public interface IRepository<T>
    {
    }
    
    public class GenericRepository<T> : IRepository<T>
    {
        public override string ToString()
        {
            return "MyRepository with type : "+typeof(T).Name;
        }
    }
    

    现在,当您运行应用程序时,您将看到所有已连线并且消息框显示封闭类型为 Process

    enter image description here

相关问题