18

私はDIとninjectに関しては初心者であり、実際の注入がいつ行われるべきか、バインディングを開始する方法について少し苦労しています。

私はすでに Web アプリケーションで使用しており、そこでは正常に動作していますが、今はクラス ライブラリでインジェクションを使用したいと考えています。

次のようなクラスがあるとします。

public class TestClass
{
    [Inject]
    public IRoleRepository RoleRepository { get; set; }
    [Inject]
    public ISiteRepository SiteRepository { get; set; }
    [Inject]
    public IUserRepository UserRepository { get; set; }

    private readonly string _fileName;

    public TestClass(string fileName)
    {
        _fileName = fileName;
    }

    public void ImportData()
    {
        var user = UserRepository.GetByUserName("myname");
        var role = RoleRepository.GetByRoleName("myname");
        var site = SiteRepository.GetByID(15);
        // Use file etc
    }

}

コンストラクターでファイル名を渡す必要があるため、ここではプロパティ インジェクションを使用します。コンストラクターパラメーターを渡す必要がある場合、コンストラクターインジェクションを使用できないというのは正しいですか? 追加のパラメーターでコンストラクター注入を使用できる場合、それらのパラメーターを渡すにはどうすればよいですか?

次のような Test クラスで消費するコンソール アプリがあります。

class Program
{
    static void Main(string[] args)
    {
        // NinjectRepositoryModule Binds my IRoleRepository etc to concrete
        // types and works fine as I'm using it in my web app without any
        // problems
        IKernel kernel = new StandardKernel(new NinjectRepositoryModule());

        var test = new TestClass("filename");

        test.ImportData();
    }
}

私の問題はtest.ImportData()、リポジトリを null と呼んだときに、リポジトリに何も注入されていないことです。別のモジュールを作成して呼び出してみました

Bind<TestClass>().ToSelf();

これですべての注入プロパティが解決されると思ったのTestClassですが、どこにも行きません。

これは些細な問題だと確信していますが、どうすればいいのかわかりません。

4

2 に答える 2

18

あなたは直接 newingしていますが、これは Ninject には傍受する方法がありません - コード変換のような魔法でsTestClassを傍受するものはないことを覚えておいてください。new

kernel.Get<TestClass>あなたは代わりにやっているはずです。

それができない場合 newは、kernel.Inject( test);

InjectウィキにvsGetなどについて語っている記事があると思います。

一般に、ダイレクトGetまたはInjectコールは、アンチパターンである Service Location の Doing It Wrong のにおいであることに注意してください。Web アプリの場合、NinjectHttpModulePageBaseは、オブジェクトの作成をインターセプトするフックです。他のスタイルのアプリにも同様のインターセプター / インターセプトする論理的な場所があります。

あなたのBind<TestClass>().ToSelf()、一般的にStandardKernelImplicitSelfBinding = trueそれを不要にするものがあります(スコープに影響を与えて 以外のものにしたい場合を除きます.InTransientScope())。

最後のスタイル ポイント:- プロパティ インジェクションを使用しています。これに正当な理由があることはめったにないため、代わりにコンストラクター インジェクションを使用する必要があります。

そして、@Mark Seemannによる .NET での Dependency Injection を購入してください。彼は、依存性注入の領域とその周辺で重要ではあるが微妙な考慮事項を数多くカバーしている優れた投稿のスタックを持っています。

于 2009-08-18T16:03:55.017 に答える
7

わかった、

Ruben さんのコメントのおかげで、必要なことを行う方法がわかりました。クラス ライブラリで使用する構成を基本的に保持する新しいモジュールを作成しました。このモジュール内で、プレースホルダー インターフェイスを使用してバインドするか、コンストラクター パラメーターを CustomerLoader に追加できます。以下は、両方の方法を示すダミー コンソール アプリのコードです。

これは、誰かが Ninject を使い始めるのに役立つかもしれません!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject.Core;
using Ninject.Core.Behavior;

namespace NinjectTest
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var kernel = new StandardKernel(new RepositoryModule(), new  ProgramModule());            
            var loader = kernel.Get<CustomerLoader>();
            loader.LoadCustomer();
            Console.ReadKey();
        }
    }

    public class ProgramModule : StandardModule
    {
        public override void Load()
        {
            // To get ninject to add the constructor parameter uncomment the line below
            //Bind<CustomerLoader>().ToSelf().WithArgument("fileName", "string argument file name");
            Bind<LiveFileName>().To<LiveFileName>();
        }
    }

    public class RepositoryModule : StandardModule
    {
        public override void Load()
        {
            Bind<ICustomerRepository>().To<CustomerRepository>().Using<SingletonBehavior>();
        }
    }

    public interface IFileNameContainer
    {
        string FileName { get; }
    }
    public class LiveFileName : IFileNameContainer
    {
        public string FileName
        {
            get { return "live file name"; }
        }
    }


    public class CustomerLoader
    {
        [Inject]
        public ICustomerRepository CustomerRepository { get; set; }
        private string _fileName;

        // To get ninject to add the constructor parameter uncomment the line below
        //public CustomerLoader(string fileName)
        //{
        //    _fileName = fileName;
        //}
        public CustomerLoader(IFileNameContainer fileNameContainer)
        {
            _fileName = fileNameContainer.FileName;
        }

        public void LoadCustomer()
        {
            Customer c = CustomerRepository.GetCustomer();
            Console.WriteLine(string.Format("Name:{0}\nAge:{1}\nFile name is:{2}", c.Name, c.Age, _fileName));
        }
    }

    public interface ICustomerRepository
    {
        Customer GetCustomer();
    }
    public class CustomerRepository : ICustomerRepository
    {
        public Customer GetCustomer()
        {
            return new Customer() { Name = "Ciaran", Age = 29 };
        }
    }
    public class Customer
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}
于 2009-08-18T22:23:45.313 に答える