Dependency injection I';我想使用依赖注入(Castle Windsor)来替换一些工厂代码I';我继承了。我是否采取了正确的方法?
这是当前代码的外观:Dependency injection I';我想使用依赖注入(Castle Windsor)来替换一些工厂代码I';我继承了。我是否采取了正确的方法?,dependency-injection,castle-windsor,Dependency Injection,Castle Windsor,这是当前代码的外观: public static class WidgetFactory { public static AbstractWidget CreateWidget(WidgetSpec spec) { if (spec.ModelNo == "FOO") return new FooWidget(spec); if (spec.ModelNo == "BAR") return new Ba
public static class WidgetFactory
{
public static AbstractWidget CreateWidget(WidgetSpec spec)
{
if (spec.ModelNo == "FOO")
return new FooWidget(spec);
if (spec.ModelNo == "BAR")
return new BarWidget(spec);
if (spec.ModelNo == "BOO")
return new BooWidget(spec);
}
}
这是我使用DI的实现:
app.config
<components>
<component id="FOO"
service="MyCo.App.AbstractWidget"
type="MyCo.App.FooWidget, MyApp"
lifestyle="transient" />
<component id="BAR"
service="MyCo.App.AbstractWidget"
type="MyCo.App.BarWidget, MyApp"
lifestyle="transient" />
....
</components>
....
代码
静态类WidgetFactory
{
静态IWindsorContainer\u container=
新WindsorContainer(新XmlTransparer(新配置资源(“城堡”));
公共静态AbstractWidget CreateWidget(WidgetSpec规范)
{
返回_container.Resolve(spec.ModelNo,new{widgetSpec=spec});
}
}
这是正确的方法吗?我忽略了什么/做错了什么/误解了什么?我应该为抽象类创建接口并从工厂返回它们吗
(对于这个特定的应用程序,我更愿意使用XML配置)
编辑:
Krzysztof Koźmic的建议:
public interface IFactory
{
AbstractFactory CreateWidget(WidgetSpec widgetSpec);
void ReleaseWidget(AbstractFactory widget);
}
public class CustomTypedFactoryComponentSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
WidgetSpec widgetSpec = arguments[0] as WidgetSpec;
if (method.Name == "CreateWidget" && arguments.Length == 1 && widgetSpec != null)
{
// The component mappings are stored as config settings
// for the sake of example
var componentName = Properties
.Settings
.Default
.Properties[widgetSpec.ModelNo]
.DefaultValue.ToString();
return componentName;
}
return base.GetComponentName(method, arguments);
}
}
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IFactory>().AsFactory(c => c.SelectedWith(new CustomTypedFactoryComponentSelector())));
//...
var factory = container.Resolve<IFactory>();
var widgetFactory = factory.CreateWidget(widgetSpec);
公共接口IFactory
{
AbstractFactory CreateWidget(WidgetSpec-WidgetSpec);
作废发布小部件(AbstractFactory小部件);
}
公共类CustomTypedFactoryComponentSelector:DefaultTypedFactoryComponentSelector
{
受保护的重写字符串GetComponentName(MethodInfo方法,对象[]参数)
{
WidgetSpec WidgetSpec=参数[0]作为WidgetSpec;
if(method.Name==“CreateWidget”&&arguments.Length==1&&widgetSpec!=null)
{
//组件映射存储为配置设置
//为了以身作则
var componentName=属性
.设置
违约
.Properties[widgetSpec.ModelNo]
.DefaultValue.ToString();
返回组件名称;
}
返回base.GetComponentName(方法、参数);
}
}
container.AddFacility();
container.Register(Component.For().AsFactory(c=>c.SelectedWith(新的CustomTypedFactoryComponentSelector()));
//...
var factory=container.Resolve();
var widgetFactory=factory.CreateWidget(widgetSpec);
您可以将类型化工厂与自定义选择器一起使用(请参阅示例和文档)。您可以将类型化工厂与自定义选择器一起使用(请参阅示例和文档)。在回答有关依赖项注入的问题时,我几乎总是说:“使用工厂”。我认为你的解决方案看起来不错;-)
不过,或许还有一些改进的空间
因为工厂是一个静态类型,所以除了直接从代码中调用它之外,您别无选择。这使得测试代码变得很困难(当然,如果可测试性是一个问题的话)。您可以尝试将工厂作为依赖项注入正在使用的类型中。因此,与其对静态类型具有硬依赖,不如在接口上创建依赖。这可能是这样的:
public interface IWidgetFactory
{
AbstractWidget CreateWidget(WidgetSpec spec);
}
internal class WidgetFactory : IWidgetFactory
{
// code
}
现在,您可以通过其接口轻松注册此类型:
<component
service="MyCo.App.IWidgetFactory, MyApp"
type="MyCo.App.WidgetFactory, MyApp"
lifestyle="singleton" />
也许这对您的应用程序是有益的。在回答关于依赖注入的问题时,我几乎总是说:“使用工厂”。我认为你的解决方案看起来不错;-) 不过,或许还有一些改进的空间 因为工厂是一个静态类型,所以除了直接从代码中调用它之外,您别无选择。这使得测试代码变得很困难(当然,如果可测试性是一个问题的话)。您可以尝试将工厂作为依赖项注入正在使用的类型中。因此,与其对静态类型具有硬依赖,不如在接口上创建依赖。这可能是这样的:
public interface IWidgetFactory
{
AbstractWidget CreateWidget(WidgetSpec spec);
}
internal class WidgetFactory : IWidgetFactory
{
// code
}
现在,您可以通过其接口轻松注册此类型:
<component
service="MyCo.App.IWidgetFactory, MyApp"
type="MyCo.App.WidgetFactory, MyApp"
lifestyle="singleton" />
也许这对您的应用程序是有益的。我遵循了这篇文章,提出了一些我认为与我的场景相关的代码。我做得对吗?我已经按照帖子写了一些我认为与我的场景相关的代码。我做得对吗?