我需要一个工厂类才能返回一个实例做一些工作,所以我有一个这样的工厂方法:
public Foo Create(string bar, IEnumerable<SomeMetaData> metaData)
{
var meta = new ObservableCollection<AnotherType>(
metaData.Select(e => new AnotherType { ... }).ToList());
return Create(new ConstructorArgument("bar", bar),
new ConstructorArgument("metaData", meta));
}
混凝土工厂类来自一个基础工厂,它可以让我查看实际布线,以防你想知道IResolutionRoot
已经消失的地方:
public abstract class FactoryBase<T> where T : class
{
private IResolutionRoot _resolutionRoot;
protected FactoryBase(IResolutionRoot resolutionRoot)
{
_resolutionRoot = resolutionRoot;
}
protected T Create(params IParameter[] parameters)
{
return _resolutionRoot.Get<T>(parameters);
}
}
(如果有人想对此评论,我对CodeReview有关于此抽象类的问题:https://codereview.stackexchange.com/questions/25038/are-there-side-effects-to-having-a-generic-ninject-factory)
问题在于,在NinjectModule中,我无法弄清楚如何告诉Ninject使用特定的具体FooFactory
类:
Bind<IFooFactory>().ToFactory(); // uses an abstract factory that doesn't do what I need
Bind<IFooFactory>().ToFactory<FooFactory>(); // doesn't build
我相信我需要的是这样的:
Bind<IFooFactory>().ToFactory<FooFactory>(Func<FooFactoryInstanceProvider>);
为了提供此InstanceProvider
,我需要做什么?
可能这只是我对Func<T>
的误解,但我发现http://www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction/对此太过模糊。
我想出了这个:
public class FooFactoryInstanceProvider : StandardInstanceProvider
{
protected override Type GetType(MethodInfo methodInfo, object[] arguments)
{
return typeof(FooFactory);
}
}
到目前为止一切顺利?下一步是什么?
答案 0 :(得分:2)
如果您已经努力实现自己的FooFactory
实现,为什么不以非工厂方式绑定它:
而不是:
Bind<IFooFactory>().ToFactory<FooFactory>();
使用:
Bind<IFooFactory>().To<FooFactory>();
如果您正在创建自己的工厂实现,那么是什么驱使您需要使用Ninject Factory Extensions中的ToFactory()
方法?
编辑1 - 使用自定义实例提供程序的工厂扩展
这样,您就可以在自定义实例提供程序中解析所需的Foo
逻辑。如果您可以获得与Foo
实现的名称匹配的逻辑,那么您就可以开展业务了。
public class BlueFiftyTwoFoo : Foo { }
Bind<IFooFactory>().ToFactory(() => new FooFactoryInstanceProvider());
并且自定义实例提供程序根据您的IFooFactory的`Create()方法参数计算出您想要的Foo
实现的名称:
public class FooFactoryInstanceProvider : StandardInstanceProvider
{
protected override string GetName(MethodInfo methodInfo, object[] arguments)
{
// harvest the 1st factory method arg, cast as appropriate
string fooParamOne = (string)arguments[0]; // ex. "Blue"
// harvest the 2nd factory method arg, cast as appropriate
string fooParamTwo = (string)arguments[1]; // ex. "FiftyTwo"
// manipulate the params to come up with the **Name** of the
// IFoo implementation you want
var fooName = GetFooName(fooParamOne, fooParamTwo);
return fooName; // ex. "BlueFiftyTwoFoo"
}
protected override ConstructorArgument[] GetConstructorArguments(MethodInfo methodInfo, object[] arguments)
{
// skip the number of params you're using above to come up with the implementation name
return base.GetConstructorArguments(methodInfo, arguments).Skip(2).ToArray();
}
private string GetFooName(string fooParamOne, string fooParamTwo)
{
// do that voodoo that you do
return fooParamOne + fooParamTwo + "Foo";
}
}