0

既存の WinForms アプリケーションに DI (Ninject を使用) を実装するプロジェクトに取り組んでいます。プロジェクト。

リポジトリのインターフェイスを必要とするコンストラクタを持つフォームを作成しようとすると、次のメッセージが表示されます。

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

Web で検索しましたが、このエラーについて読んだ記事のほとんどは、はるかに複雑な設定を扱っているか、パラメーターの挿入に関するものであり、ここでの問題かどうかはわかりません。

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 に答える