When injecting dependencies into a constructor, I'm not quite sure if it breaks SOLID if I do the following:
public MyClass(IConfiguration configuration)
{
_port = configuration.GetValue("Port");
}
instead of passing the pure value like so:
public MyClass(int port)
{
_port = port;
}
The first one seems to be some kind of a Service Locator.
Question here is: Is it okay to pass complex dependencies just to retrieve a single value the class actually relies on?
To me it doesn't look that wrong, but it unnecessarily hides the real dependency which could get passed much easier.
From perspective of the SOLID principles, I see no clear violation:
IConfigurationdoesn't change the number of responsibilities thatMyClasshas.IConfiguration.IConfigurationhas no impact on LSP.IConfigurationis wide and violates ISP. From just this code, however, I would say there is no ISP problem.IConfigurationis a framework-defined abstraction, we might consider this code to violate the DIP. But it's not always possible or feasible to remove all dependencies to framework abstractions, so we should be pragmatic. Whether or not it is pragmatic to take a dependency onIConfigurationis impossible to say in your case.There is, however, other guidance besides the SOLID principles that might help us out here:
MyClassconstructor, however, is usingIConfigurationinside the constructor.IConfiguration) with broad capabilities. In your question you are referring to the Service Locator anti-pattern in this regards. Although injectingIConfigurationcan certainly not be regarded as a Service Locator, from loading configuration values,IConfigurationas similar capabilities. It's better to narrow this down and be as explicit as possible andint portis much more explicit compared toIConfiguration.So with all that in place, let me try to answer your question:
Considering the guidance on DI above, I would say that it is better to either inject
int port, or a typed configuration class that wrapsint port, that is specific toMyClass; e.g.MyClassSettings:Both convey the same amount of information, but the latter is less ambiguous, as
intcould mean anything, whileMyClassSettingsis very precise and easily resolved from a DI Container.