如何使用ninject工厂,该工厂使用构造函数参数创建实例,而不依赖于参数名称 .
问题是 ToConstructor()
-Method不起作用,因为我将它绑定到泛型定义 .
以下示例有效,如果我使用带有相应构造函数参数名称的factory方法,但我不喜欢它依赖于名称 .
因为以下解决方案非常脆弱,如果有人选择了错误的名称或重命名派生类中的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
{
}
1 回答
工厂扩展具有以下约定:参数必须与它们将传递给的构造函数参数具有相同的名称 . 没有简单的方法可以采用不同的方式 . 我能想到的唯一方法是关于以下内容:
创建一个新的IParameter实现,该实现可以包含对IDependencyA的引用 .
创建硬编码工厂或自定义IInstanceProvider(请参阅文档),创建IParameter实现的实例,以便将其传递给Get <>请求
为IDependencyA添加新绑定:
Bind<IDependency>().ToMethod(ctx => extract and return your parameter from the context)