1

引数名に依存せずに、コンストラクター パラメーターを使用してインスタンスを作成する ninject ファクトリを使用するにはどうすればよいですか。

問題は、ToConstructor()-Method が機能しないことです。これは、一般的な定義にバインドしているためです。

次の例は、対応するコンストラクター引数名でファクトリ メソッドを使用すると機能しますが、名前に依存するのは好きではありません。

次の解決策は非常に脆弱であり、誰かが間違った名前を選択したり、派生クラスの ctor-argument の名前を変更したりすると機能しなくなるためです。

解決策はありますか?

コード例は次のとおりです。

[TestFixture]
public class NinjectFactoryBindingsTest
{
    [Test]
    public void ConstructorSelectionWithArguments()
    {
        NinjectSettings ninjectSettings = new NinjectSettings();
        ninjectSettings.LoadExtensions = false;

        using (var kernel = new StandardKernel(ninjectSettings, new FuncModule()))
        {
            // IDependencyA will be passed to the factory, therefore it is not bounded
            //kernel.Bind<IDependencyA>().To<DependencyA>();
            kernel.Bind<IDependencyB>().To<DependencyB>();

            kernel.Bind(typeof(IGenericBaseClass<>)).To(typeof(GenericDerivedClass<>));
            kernel.Bind<IGenericClassFactory>().ToFactory();

            IGenericClassFactory factory = kernel.Get<IGenericClassFactory>();

            DependencyA dependencyA = new DependencyA();

            IGenericBaseClass<GenericImpl> shouldWorkInstance = factory.Create<GenericImpl>(dependencyA);

            Assert.NotNull(shouldWorkInstance);

        }
    }
}    

public interface IGenericClassFactory
{
    IGenericBaseClass<TGeneric> Create<TGeneric>(IDependencyA someName) where TGeneric : IGeneric;
    // This works, but relies on ctor-param-names!!!
    // IGenericBaseClass<TGeneric> Create<TGeneric>(IDependencyA otherNameThanInBaseClass) where TGeneric : IGeneric; 
}

public class DependencyA : IDependencyA
{
}

public class DependencyB : IDependencyB
{
}

public class GenericDerivedClass<TGeneric> : GenericBaseClass<TGeneric> where TGeneric : IGeneric
{
    public GenericDerivedClass(IDependencyA otherNameThanInBaseClass, IDependencyB dependencyB)
        : base(otherNameThanInBaseClass, dependencyB)
    {
    }
}

public abstract class GenericBaseClass<TGeneric> : IGenericBaseClass<TGeneric> where TGeneric : IGeneric
{
    protected GenericBaseClass(IDependencyA dependencyA, IDependencyB dependencyB)
    {
    }
}

public interface IGenericBaseClass<TGeneric> where TGeneric : IGeneric
{
}

public interface IDependencyB
{
}

public interface IDependencyA
{
}

public class GenericImpl : IGeneric
{
}

public interface IGeneric
{
}
4

1 に答える 1

1

ファクトリ拡張には、引数が渡されるコンストラクタ引数と同じ名前を持たなければならないという規則があります。それを別の方法で行う簡単な方法はありません。私が考えることができる唯一の方法は、次のことです。

  1. IDependencyA への参照を保持できる新しい IParameter 実装を作成します。
  2. Get<> リクエストに渡されるように、IParameter 実装のインスタンスを作成する、ハードコードされたファクトリまたはカスタム IInstanceProvider (ドキュメントを参照) を作成します。
  3. IDependencyA の新しいバインドを追加します。Bind<IDependency>().ToMethod(ctx => extract and return your parameter from the context)
于 2013-07-19T22:46:14.407 に答える