Does Simple Injector have a RegisterConditional method with a factory object?

I see a simple injector container has this method

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

But I want to use a different object of the same implementation for different services, so the overloaded method that I need will look like this:

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

But SimpleInjector does not have it. I am trying to find other container methods for registering an instance creator with a condition for a service. Are there any other ways that I can do?

Or, what I'm trying to do is not in a good design, so the developers do not implement it?

Edited: Added an example and a more detailed question.

Example

 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") 

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

+5
source share
1 answer

Or, what I'm trying to do is not in a good design, so the developers do not implement it?

After looking at your example, I have to conclude that there may be a design flaw. The main design problem is that you seem to be violating the Liskov Substitution Principle (LSP). LSP is one of the principles of SOLID and argues that subclasses (or interface implementations) should be interchangeable for each other without affecting the consumer. However, in your application, XMLFileScanner seems to break when it comes with a CSV file.

So, from the point of view of LSP, this means that both versions of the file scanner deserve their own abstraction. After you give them your own abstraction, the problem will completely disappear.

If, however, replacing file locators does not affect the operation of file scanners (for example, because they are not read, but simply written), the LSP is not broken, and the design is fine.

If changing abstractions is impossible or the LSP is not broken, the option is to register file scanners with the factory delegate or simply creating it once as a singleton. This gives you complete control over the composition of this part of the graphic. For instance:

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

But SimpleInjector does not have it. I am trying to find other container methods for registering an instance creator with a condition for a service. Are there any other ways that I can do?

In fact, you can use RegisterConditional methods for this, but this function is a bit hidden, and this is intentional. Simple Injector tries to advance the construction of graphs of objects that are fully known at the start-up phase and prevents the construction of graphs of objects based on execution conditions. Using the Func<TService> instanceCreator delegate allows you to create execution conditions and why there is no underloading.

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); 
+7
source

Source: https://habr.com/ru/post/1237403/


All Articles