4

我需要一个工厂类在它返回一个实例之前做一些工作,所以我有一个这样的工厂方法:

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 -工厂

问题是在 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);
    }
}

到目前为止,一切都很好?下一步是什么?

4

1 回答 1

3

如果您已经努力进行自己的实现,为什么不以非工厂FooFactory方式绑定到它:

代替:

Bind<IFooFactory>().ToFactory<FooFactory>();

利用:

Bind<IFooFactory>().To<FooFactory>();

如果您正在创建自己的工厂实现,那么究竟是什么驱使您需要使用ToFactory()Ninject Factory Extensions 中的方法?

编辑 1 - 将工厂扩展与自定义实例提供程序一起使用

这样,您将解决所需的逻辑放在Foo自定义实例提供程序中。如果您可以获得与实现名称相匹配的逻辑Foo,那么您就在做生意。

public class BlueFiftyTwoFoo : Foo { }

Bind<IFooFactory>().ToFactory(() => new FooFactoryInstanceProvider());

并且自定义实例提供程序Foo根据您的 IFooFactory 的 `Create() 方法参数确定您想要的实现的名称,如下所示:

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";
    }
}
于 2013-04-12T19:58:09.213 回答