C# 温莎城堡抽象工厂
我试图理解如何使用C# 温莎城堡抽象工厂,c#,dependency-injection,castle-windsor,C#,Dependency Injection,Castle Windsor,我试图理解如何使用TypedFactoryFacility创建抽象工厂,我让它在一个基本级别上工作,但是我不完全理解如何使用运行时依赖项来扩展它 假设我有一个需要在运行时创建的服务: public interface IRuntimeService { void DoThing(); } 通过以下实现 public class RuntimeService : IRuntimeService { public void DoThing() { // Do some work
TypedFactoryFacility
创建抽象工厂,我让它在一个基本级别上工作,但是我不完全理解如何使用运行时依赖项来扩展它
假设我有一个需要在运行时创建的服务:
public interface IRuntimeService {
void DoThing();
}
通过以下实现
public class RuntimeService : IRuntimeService {
public void DoThing() {
// Do some work
}
}
为了创建我的IRuntimeService
,我创建了一个抽象工厂
public interface IRuntimeServiceFactory {
IRuntimeService CreateService();
}
在我的Castle安装程序中,我使用TypedFactoryFacility
注册我的类和抽象工厂
public class TypeInstaller : IWindsorInstaller {
public void Install(IWindsorContainer container, IConfigurationStore store) {
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IRuntimeService>().ImplementedBy<RuntimeService>());
container.Register(Component.For<IRuntimeServiceFactory>().AsFactory());
}
上面的一切都可以完美地工作,但是当我的
RuntimeService
类需要注入包含运行时参数的依赖链时,我遇到了一个问题
为了扩展上面的示例,假设我有一个新的运行时依赖项
public interface IRuntimeDependency {
void DoWork();
}
public class RuntimeService : IRuntimeService {
private readonly IRuntimeDependency m_Dep;
public RuntimeService(IRuntimeDependency dep) {
m_Dep = dep;
}
public void DoThing() {
// Do some work involving the dependency
m_Dep.DoWork();
}
}
由通过构造函数获取运行时字符串值的类实现
public class RuntimeDependency : IRuntimeDependency {
private readonly string m_Param;
public RuntimeDependency(string param) {
m_Param = param;
}
public void DoWork() {
// Do work involving the param
}
}
以前定义的服务类现在需要对依赖项的引用
public interface IRuntimeDependency {
void DoWork();
}
public class RuntimeService : IRuntimeService {
private readonly IRuntimeDependency m_Dep;
public RuntimeService(IRuntimeDependency dep) {
m_Dep = dep;
}
public void DoThing() {
// Do some work involving the dependency
m_Dep.DoWork();
}
}
我现在如何使用TypedFactoryFacility
创建我的服务实例
我希望你能改变我的工厂方法
IRuntimeService CreateService(string param);
但Windsor抛出错误“无法解析参数“param”类型“System.String”的非可选依赖项”
如果我给它一个字符串,温莎知道如何创建IRuntimeDependency
,如果我给它一个依赖项,温莎知道如何创建IRuntimeService
,那么为什么它不能直接用字符串参数创建IRuntimeService
我可以通过两种不同的工厂方法来实现
IRuntimeService CreateService(IRuntimeDependency dep);
IRuntimeDependency CreateDependency(string param);
并手动创建依赖项
var dep = m_ServiceFactory.CreateDependency(param);
var myService = m_ServiceFactory.CreateService(dep );
^^^^这很有效,但使用容器的全部意义在于它可以为我组装新对象。这是一个只涉及一个依赖项的相对简单的示例,但如果使用更复杂的对象图,它很容易失控
当然,我可以创建自己的工厂实现,但这也抵消了使用TypedFactoryFacility
的好处,它应该为您创建抽象工厂实现。我很难相信这个问题没有现成的解决方案,但是Windsor示例不包含任何链式的运行时依赖项
我认为使用
FactoryComponentSelector
不是正确的方法,因为创建RuntimeService
实例只有一种可能的路径。它应该能够自动解析。在许多或大多数情况下,容器解析的对象取决于容器解析的其他接口的实现。因此,只要所有接口都注册了实现,容器就可以解析整个依赖链
但是在本例中,RuntimeDependency
依赖于字符串,而该字符串不是容器可以解析的
public RuntimeDependency(string param) {
m_Param = param;
}
在这种情况下,您可以使用DependsOn
方法显式提供一个值来实现该依赖关系
container.Register(Component.For<IRuntimeDependency, RuntimeDependency>()
.DependsOn(Dependency.OnValue("param","whatEverTheValueIs")));
container.Register(Component.For())
.DependsOn(Dependency.OnValue(“param”,“whatEverTheValueIs”));
当然,该值可以来自配置或其他任何地方。我经常在SQL连接字符串中使用它。在许多或大多数情况下,容器解析的对象依赖于容器解析的其他接口的实现。因此,只要所有接口都注册了实现,容器就可以解析整个依赖链 但是在本例中,
RuntimeDependency
依赖于字符串,而该字符串不是容器可以解析的
public RuntimeDependency(string param) {
m_Param = param;
}
在这种情况下,您可以使用DependsOn
方法显式提供一个值来实现该依赖关系
container.Register(Component.For<IRuntimeDependency, RuntimeDependency>()
.DependsOn(Dependency.OnValue("param","whatEverTheValueIs")));
container.Register(Component.For())
.DependsOn(Dependency.OnValue(“param”,“whatEverTheValueIs”));
当然,该值可以来自配置或其他任何地方。我经常在SQL连接字符串中使用这一点。似乎我所要求的是设计上不可能实现的 看到这个答案了吗
看来我所要求的是设计上不可能的 看到这个答案了吗 可以使用
container.Register(Component.For())
.由()实施
.生活方式
.动态参数((k,d)=>{
d[“dep”]=新的RuntimeDependency((字符串)d[“param”]);
}));
请记住,字典键必须与CreateService
方法和RuntimeService
构造函数中的参数名匹配
编辑:如果每次调用factory方法时都要创建一个新实例,那么也应该这样做。(默认为单例)可以使用
container.Register(Component.For())
.由()实施
.生活方式
.动态参数((k,d)=>{
d[“dep”]=新的RuntimeDependency((字符串)d[“param”]);
}));
请记住,字典键必须与CreateService
方法和RuntimeService
构造函数中的参数名匹配
编辑:如果每次调用factory方法时都要创建一个新实例,那么也应该这样做。(默认值为singleton)太好了,我认为这让我走上了正确的道路,但我的参数不是静态值,而是在运行时传入的参数。如何将传入工厂的值映射到
RuntimeDependency
构造函数?字符串来自何处?任何依赖于物体的东西都不能通过它,所以它一定是环保的。也许你需要的不是一个字符串,而是另一个对象,当你需要它时,它提供你需要的字符串。它不是环境的,它是一个从文件加载的运行时参数