5

Ninject Factory拡張機能を使用すると、ファクトリを自動的に生成し、ファクトリにパラメータをクラスのコンストラクタに渡すことができます。次のテストに合格します。

public interface IBar
{
    int Foo { get; }
}

public class Bar : IBar
{
    int _foo;
    public Bar(int foo) { _foo = foo; }
    public int Foo { get { return _foo; } }
}

public interface IBarFactory
{
    IBar CreateTest(int foo);
}

[Test]
public void ExecuteTest()
{
    var kernel = new StandardKernel();
    kernel.Bind<IBar>().To<Bar>();
    kernel.Bind<IBarFactory>().ToFactory();
    var factory = kernel.Get<IBarFactory>();
    var actual = factory.CreateTest(42);
    Assert.That(actual, Is.InstanceOf<Bar>());
}

ただし、私の特定の問題では、次のように、クラス自体ではなく、構築しているクラスの依存関係にファクトリ引数を渡したいと思います。

public interface IBarContainer
{
    IBar Bar { get; }
}

public class BarContainer : IBarContainer
{
    IBar _bar;
    public BarContainer(IBar bar) { _bar = bar; }
    public IBar Bar { get { return _bar; } }
}

public interface ITestContainerFactory
{
    IBarContainer CreateTestContainer(int foo);
}

[Test]
public void ExecuteTestContainer()
{
    var kernel = new StandardKernel();
    kernel.Bind<IBar>().To<Bar>();
    kernel.Bind<IBarContainer>().To<BarContainer>();
    kernel.Bind<ITestContainerFactory>().ToFactory();
    var factory = kernel.Get<ITestContainerFactory>();
    var actual = factory.CreateTestContainer(42);
    Assert.That(actual.Bar, Is.InstanceOf<Bar>());
}

このテストは次のメッセージで失敗します。

Ninject.ActivationException:intのアクティブ化中にエラーが発生しました一致するバインディングが利用できず、タイプは自己バインドできません。アクティベーションパス:
3)タイプBarのコンストラクターのパラメーターfooへの依存性intの
注入2)タイプBarContainerのコンストラクターのパラメーターバーへの依存性IBarの注入
1)IBarContainerの要求

'Bar'依存関係を解決するときに渡された'foo'引数を使用したいことをファクトリに認識させる方法はありますか?

4

3 に答える 3

4

やあ、デフォルトのインスタンス プロバイダは、継承されたコンストラクタ引数を使用しません。この動作を変更するには、次のように独自のインスタンス プロバイダーを記述します。

public class CustomInstanceProvider : StandardInstanceProvider {
    protected override ConstructorArgument[] 
        GetConstructorArguments(MethodInfo methodInfo, object[] arguments) 
        {
            var parameters = methodInfo.GetParameters();
            var constructorArguments = 
                new ConstructorArgument[parameters.Length];
            for (int i = 0; i < parameters.Length; i++)
            {
                constructorArguments[i] = 
                    new ConstructorArgument
                        (parameters[i].Name, arguments[i], true);
            }
            return constructorArguments;
        }
}

次に、提供されたものではなく独自のものを使用するように ninject に指示するだけです。

それが役立つことを願っています

于 2012-06-27T21:58:56.763 に答える
3

Ninject.Extensions.Factory のバージョン 3.2.0 から、これは以下を使用してネイティブにサポートされます。

Ninject.Extensions.Factory.TypeMatchingArgumentInheritanceInstanceProvider

次のように使用できます。

kernel.Bind<IxxxFactory>()
   .ToFactory(() => new TypeMatchingArgumentInheritanceInstanceProvider());

ソースコードを見ると、以前の回答に基づいています。

于 2015-08-14T08:43:10.680 に答える
1

あなたの質問を正しく理解していれば、このNinject Wikiの記事には、 new .ToFactory() バインディング拡張機能の使用方法、および生成されたファクトリを取得してコンストラクターであるオブジェクトを作成する方法に関する良い例( Factory インターフェイス)があると思いますパラメータがあります。

于 2012-10-26T14:09:32.883 に答える