Подтвердить что ты не робот

Инъекция зависимостей в WinForms с использованием Ninject и Entity Framework

В настоящее время я работаю над проектом, в котором мы конвертируем наше старое приложение DataSet, Stored Procedure WinForm для использования Entity Framework, чтобы новые веб-сайты могли обращаться к одной и той же объектной модели и репозиториям.

В любом случае, я пытаюсь внедрить Injection Dependency в формы, чтобы мы могли использовать посмеянные репозитории для модульного тестирования. Я использую Ninject по той простой причине, которую я использовал ранее на веб-сайтах MVC, однако попытка реализовать это в приложении WinForm оказалась, по меньшей мере, проблематичной, еще больше затруднялась из-за отсутствия информации о DI в WinForms на в Интернете.

До сих пор я создал Ninject Factory и репозитории, но мне не удавалось впрыскивать репозитории в формы.

Поэтому кто-нибудь может мне помочь или сделать какие-либо предложения?

Ниже у меня есть части моего кода, которые могут помочь:

Ninject Factory:

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

Я понимаю, что мой вопрос немного расплывчатый, но я не уверен, где лежит проблема или что мне нужно выполнить.

Большое спасибо

4b9b3361

Ответ 1

Вы создаете состав root как одну точку входа для своих разрешений. Вы передаете INjectModule в качестве параметра, чтобы вы могли его конфигурировать, он тестирует по-разному. Одним из преимуществ Root Composition является то, что не все ваши сборки будут зависеть от 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<>));
    }
}

В основном методе вы передаете 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