我已经阅读了很多关于这个主题的内容,但是无法一直掌握它 .
我试图使用 Ninject.Extensions.Factory 而不是我的工厂根据用户输入创建新对象 . 我想充分利用Ninject功能和IoC概念 .
Now the code looks like this:
interface IFeatureFactory
{
IFeature createFeature(int input);
}
and:
class BasicFeatureFactory : IFeatureFactory
{
public IFeature createFeature(int input)
{
switch (input)
{
case 1:
return new FirstFeature();
case 2:
return new SecondFeature();
default:
return null;
}
}
}
在将来, IFeature 将具有依赖关系,所以我想以 IoC 方式进行 .
EDIT:
consumer class - IFeatureFactory 和 IUILayer 被注入 FeatureService 构造函数并使用 Ninject 解析 .
private IFeatureFactory featureFactory;
private IUILayer uiHandler;
public FeatureService(IFeatureFactory featureFactory, IUILayer uiHandler)
{
this.featureFactory = featureFactory;
this.uiHandler = uiHandler;
}
public void startService()
{
int userSelection = 0;
uiHandler.displayMenu();
userSelection = uiHandler.getSelection();
while (userSelection != 5)
{
IFeature feature = featureFactory.createFeature(userSelection);
if (feature != null)
{
IResult result = feature.execFeature();
uiHandler.displayResult(result);
}
else
{
uiHandler.displayErrorMessage();
}
uiHandler.displayMenu();
userSelection = uiHandler.getSelection();
}
}
and IFeature class:
public interface IFeature
{
IResult execFeature();
}
Bindings:
public override void Load()
{
Bind<IFeatureFactory>().To<BasicFeatureFactory>();
Bind<IUILayer>().To<ConsoleUILayer>();
}
如何用 Ninject.Extensions.Factory 将 Factory Pattern 转换为 IoC ?请记住 IFeature 的创建取决于用户输入 .
2 回答
对我来说,看起来你有2个选项来重构代码以获得ninject的全部好处 .
你现在的工作方式与pure di没什么不同(它没有任何问题,在某些情况下它更好)但正如你所说,你想要完全使用ninject功能 .
Option one
而不是将IFeatureFactory注入FeatureService注入接口IFeatureProvider,它将如下所示:
现在,您的FeatureService将从此提供程序而不是工厂获取所请求的功能 .
您将需要实现IFeatureProvider,为此您将需要另外2个接口IFirstFeatureFactory和ISecondFeatureFactory:
现在,IFeatureProvider的阻碍:
你应该注意到我只是将负责'new'的对象提取到另一个界面 .
我们不会实现两个工厂接口,因为如果我们正确绑定它,ninject将为我们做 .
绑定:
这个'NameLikeFactoryMethod'绑定等同于命名绑定的使用,因为我做here,它现在是the recommended way by ninject for factories .
需要注意的重要事项是你自己没有实现IFirstFeatureFactory和ISecondFeatureFactory,而你正在使用ninject functionallity .
这个选项的主要缺点是当我们需要添加我们需要创建的更多功能时,除了功能本身另一个FeatureFactory之外,还要更改FeatureProvider来处理它 . 如果功能不经常更改,这个选项可能很好而且简单,但如果他们这样做可能会成为维护噩梦,这就是为什么我建议选项2 .
Option two
在这个选项中,我们根本不会创建任何提供者类,并将所有创建逻辑放在工厂中 .
IFeatureFactory接口看起来与你现在的接口非常相似,但不是使用int作为参数,我们将使用一个字符串(更适合命名绑定,我们很快就会看到) .
我们不会自己实现这个接口,让ninject为我们做,但是我们需要告诉ninject使用CearteFeature的第一个参数来检测要实例化的实现(FirstFeatue或SecondFeature) .
为此,我们需要具有此行为的自定义实例提供程序作为StandardInstanceProvider,使用其他约定来选择要实例化的实现(默认约定in this article) .
幸运的是,ninject显示了我们如何通过UseFirstArgumentAsNameInstanceProvider快速实现它 .
现在绑定:
这里要注意的事情:
我们不会自己实现工厂界面 .
我们正在为每个实现使用命名绑定,我们将根据我们将传递给工厂方法的featureName从工厂获得实现(这就是我更喜欢参数为字符串的原因) .
请注意,如果您传递的功能名称不是"FirstFeature"或将抛出"SecondFeature"异常 .
我们正在使用UseFirstArgumentAsNameInstanceProvider作为我们工厂的实例提供程序,如前所述 .
这解决了第一个选项中的问题,好像我们想要添加新功能,我们只需要创建它并将其与他的名称绑定到他的界面 .
现在工厂的客户可以从工厂特征中询问这个新名称,而无需更改其他类 .
Conslucsion
通过选择上面的选项之一而不是纯粹的di,我们将获得让ninject内核在工厂中创建我们的对象而不是自己完成所有'new'的好处 .
虽然没有使用IoC容器没有任何问题,但这确实可以帮助我们解决问题是一个在IFeature实现中的大依赖图,因为ninject会为我们注入它们 . 通过执行这些选项之一,我们完全使用ninject功能而不使用'Service locator',这被视为反模式 .
您可以将功能注入
BasicFeatureFactory
的构造函数中 .