我看到Simple Injector的Container有这种方法
public void RegisterConditional( Predicate predicate )
但是我想为不同的服务使用相同实现的不同对象,所以我需要的重载方法看起来像这样
public void RegisterConditional( Func instanceCreator, Predicate predicate )
但SimpleInjector没有它.我正在尝试找到其他Container的方法来注册具有服务条件的实例创建者.还有其他方法吗?
或者,我正在努力做的不是好的设计,所以开发人员不实现它?
编辑:添加了示例和更详细的问题.
例
class CSVFileScanner { public CSVFileScanner(IFileLocator fileLocator) { } } class XMLFileScanner { public XMLFileScanner(IFileLocator fileLocator) { } } class DefaultLogFileLocator: ILogFileLocator { public DefaultLogFileLocator(string directoryPath, string searchPattern) { } } var locatorForCSVFileScanner = new DefaultLogFileLocator("C:\CSVLogDir", "*.csv") var locatorForXMLFileScanner = new DefaultLogFileLocator("C:\XMLLogDir", "*.xml")
从示例源代码,我怎么能注册他们得到 locatorForCSVFileScanner
传递给对象CSVFileScanner
时,构造CSVFileScanner
越来越创建并locatorForXMLFileScanner
传递给对象XMLFileScanner
构造函数时XMLFileScanner
得到产生的?
或者,我正在努力做的不是好的设计,所以开发人员不实现它?
在看到你的例子之后,我必须得出结论,可能存在设计缺陷.设计的主要问题是您似乎违反了Liskov替换原则(LSP).LSP是SOLID原则之一,并声明子类(或接口的实现)应该可以互换,而不会影响消费者.但是,在您的应用程序中,XMLFileScanner
当它提供CSV文件时似乎会中断.
因此,从LSP的角度来看,这意味着两个文件扫描程序实现都应该得到自己的抽象.一旦你给自己的抽象,问题就会完全消失.
但是,如果交换文件定位器对文件扫描程序的工作没有影响(例如因为它们不读取,而只是写入),则不会违反LSP并且设计没有问题.
如果改变抽象是不可行的或LSP没有被违反,则可以选择使用工厂代表注册文件扫描程序,或者只需将其创建为单例.这使您可以完全控制对象图的该部分的组成.例如:
container.RegisterSingleton( new CSVFileScanner(new DefaultLogFileLocator("C:\CSVLogDir", "*.csv"))); container.RegisterSingleton ( new XMLFileScanner(new DefaultLogFileLocator("C:\XMLLogDir", "*.xml")));
但SimpleInjector没有它.我正在尝试找到其他Container的方法来注册具有服务条件的实例创建者.还有其他方法吗?
你实际上可以使用这些RegisterConditional
方法实现这一点,但这个功能有点隐藏,这是故意的.Simple Injector尝试推动在启动阶段完全已知的对象图的构造,并阻止基于运行时条件构建对象图.使用Func
委托允许创建运行时条件,这就是为什么缺少这样的重载.
然而,这样做的方法如下:
var csv = Lifestyle.Singleton.CreateRegistration( () => new DefaultLogFileLocator("C:\\CSVLogDir", "*.csv"), container); var xml = Lifestyle.Singleton.CreateRegistration ( () => new DefaultLogFileLocator("C:\\XMLLogDir", "*.csv"), container); container.RegisterConditional(typeof(IFileLocator), csv, WhenInjectedInto ); container.RegisterConditional(typeof(IFileLocator), xml, WhenInjectedInto ); // Helper method. static bool WhenInjectedInto (PredicateContext c) => c.Consumer.ImplementationType == typeof(T);