I see Simple Injector's Container has this method
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
)
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.
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 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?
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.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.
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:
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 aFunc<TService> instanceCreator
delegate allows making runtime conditions and that's why such overload is missing.The way to do this however is as follows: