Simple Injector是否可以通过对象工厂注册RegisterConditional? [英] Does Simple Injector have a way to RegisterConditional with object factory?

查看:67
本文介绍了Simple Injector是否可以通过对象工厂注册RegisterConditional?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到简单注入器的容器具有此方法

public void RegisterConditional<TService, TImplementation>(
    Predicate<PredicateContext> predicate
)

但我想使用其他不同服务的同一实现的对象,因此我需要的重载方法如下所示:

But I want to use the different object of the same implementation for different service, so what overloaded method I need would look like this

public void RegisterConditional<TService>(
    Func<TService> instanceCreator,
    Predicate<PredicateContext> predicate
)

但是SimpleInjector没有它。我正在尝试找到其他Container的方法,以在服务条件下注册实例创建者。
还有其他我可以做的方法吗?

But the SimpleInjector doesn't have it. I am trying to find the other Container's methods to register instance creator with condition for the service. Is there the other ways else I can do?

或者,我试图做的不是好的设计,所以开发人员没有实现

Or, is what I am trying to do not the good design, so the developers don't implement it?

已编辑:添加了示例和更详细的问题。

Edited: Added example and the more detailed question.

示例

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 对象传递给 CSVFi创建 CSVFileScanner 并将 locatorForXMLFileScanner 对象传递给构造函数创建 XMLFileScanner 时> XMLFileScanner 构造函数?

From the example source code, how can I register them to get locatorForCSVFileScanner object passed to the CSVFileScanner constructor when CSVFileScanner getting created and locatorForXMLFileScanner object passed to the XMLFileScanner constructor when XMLFileScanner getting created?

推荐答案


或者,我试图做的不是好的设计,所以开发人员没有实现它?

Or, is what I am trying to do not the good design, so the developers don't implement it?

看到您的示例后,我必须得出结论,可能存在设计缺陷。该设计的主要问题是您似乎违反了 Liskov替代原则(LSP)。 LSP是SOLID原则之一,并声明子类(或接口的实现)应可互换,而不会影响使用者。但是,在您的应用程序中, XMLFileScanner 随CSV文件一起提供时似乎坏了。

After seeing your example I have to conclude that there might be a design flaw. The main issue with the design is that you seem to violate the Liskov Substitution Principle (LSP). LSP is one of the SOLID principles and states that sub classes (or implementations of interfaces) should be interchangeable for one another, without affecting the consumer. In your application however, the XMLFileScanner seems to break when it is supplied with a CSV file.

从LSP的角度来看,这意味着两种文件扫描程序实现都应该拥有自己的抽象。一旦提供了它们自己的抽象,问题将完全消失。

So from a perspective of the LSP, this means that both file scanner implementations deserve their own abstraction. Once you give both their own abstraction, the problem will go away completely.

但是,如果交换文件定位符对文件扫描程序的工作没有影响(例如,因为

If however swapping the file locators has no effect on the working of the file scanners (for instance because they don't read, but just write), LSP is not violated and the design is okay.

如果更改抽象概念不可行或不违反LSP,则不会选项是使用工厂委托或仅将其创建为单例一次来注册文件扫描器。这使您可以完全控制对象图的该部分的组成。例如:

If altering the abstractions is not feasible or LSP is not violated, an option is to register the file scanners using a factory delegate or by simply creating it once as singleton. This gives you full control over the composition of that part of the object graph. For instance:

container.RegisterSingleton<CSVFileScanner>(
    new CSVFileScanner(new DefaultLogFileLocator("C:\CSVLogDir", "*.csv")));

container.RegisterSingleton<XMLFileScanner>(
    new XMLFileScanner(new DefaultLogFileLocator("C:\XMLLogDir", "*.xml")));




但是SimpleInjector没有它。我正在尝试找到其他Container的方法,以在服务条件下注册实例创建者。还有其他其他方法吗?

But the SimpleInjector doesn't have it. I am trying to find the other Container's methods to register instance creator with condition for the service. Is there the other ways else I can do?

您实际上可以使用 RegisterConditional 实现此目的的方法,但是此功能有点隐藏,这是有意的。 Simple Injector尝试促进在启动阶段完全了解的对象图的构造,并阻止基于运行时条件构造对象图。 Func< TService>的使用instanceCreator 委托允许创建运行时条件,这就是为什么没有这种重载的原因。

You can actually use the RegisterConditional methods to achieve this, but this feature is a bit hidden, and this is deliberate. Simple Injector tries to promote the construction of object graphs that are completely known in the startup phase and discourages building object graphs based on runtime conditions. The use of a Func<TService> instanceCreator delegate allows making runtime conditions and that's why such overload is missing.

然而,执行此操作的方法如下:

The way to do this however is as follows:

var csv = Lifestyle.Singleton.CreateRegistration<IFileLocator>(
    () => new DefaultLogFileLocator("C:\\CSVLogDir", "*.csv"), container);

var xml = Lifestyle.Singleton.CreateRegistration<IFileLocator>(
    () => new DefaultLogFileLocator("C:\\XMLLogDir", "*.csv"), container);

container.RegisterConditional(typeof(IFileLocator), csv, WhenInjectedInto<CSVFileScanner>);
container.RegisterConditional(typeof(IFileLocator), xml, WhenInjectedInto<XMLFileScanner>);

// Helper method.
static bool WhenInjectedInto<T>(PredicateContext c) =>
    c.Consumer.ImplementationType == typeof(T);

这篇关于Simple Injector是否可以通过对象工厂注册RegisterConditional?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆