19

私は現在、古いDataSet、ストアドプロシージャWinFormアプリケーションをEntity Frameworkを使用するように変換して、新しいWebサイトが同じオブジェクトモデルとリポジトリにアクセスできるようにするプロジェクトに取り組んでいます。

とにかく、ユニットテストにモックリポジトリを使用できるように、フォームに依存性注入を実装しようとしています。以前MVCWebサイトで使用した単純な理由でNinjectを使用していますが、WinFormアプリケーションでこれを実装しようとすると、控えめに言っても問題が発生し、WinFormsのDIに関する情報が不足しているためにさらに妨げられます。ウェブ。

これまでにNinjectFactoryとリポジトリを作成しましたが、リポジトリをフォームに注入することはあまりできませんでした。

したがって、誰かが私を助けたり、何か提案をしたりできますか?

以下に、役立つ可能性のあるコードの一部を示します。

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

私の質問は少し曖昧であることは理解していますが、問題がどこにあるのか、何を完了する必要があるのか​​わかりません。

どうもありがとう

4

1 に答える 1

37

解決策の 1 つのエントリ ポイントとしてコンポジション ルートを作成します。INjectModule をパラメーターとして渡すと、別の方法でテストするように構成できます。コンポジション ルートの利点の 1 つは、すべてのアセンブリが NInject に依存するわけではなく、解決ロジックを変更する 1 つのポイントがあることです。将来的に 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<>));
    }
}

ApplicationModulemain メソッドでは、パラメーターとして渡し、解決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

ここに画像の説明を入力

于 2013-01-04T12:41:51.347 に答える