Everything works fine till the constructors of the realizations are the same. However, I have a sort of dilemma when the constructors are different. Is it okay or maybe there is an architecture issue? Here is the code:
public class CategoryViewFactory : ICategoryViewFactory
{
private readonly ActiveProgressions _activeProgressions;
public CategoryViewFactory(ActiveProgressions activeProgressions)
{
_activeProgressions = activeProgressions;
}
public ICategoryView? Create(CategoryType type, Category category)
{
return type switch
{
CategoryType.Category => new CategoryView(category),
CategoryType.Subcategory => new SubcategoryView(category, _activeProgressions),
_ => null
};
}
}
ActiveProgression is a singleton service which I inject using the container. Is it okay? And what I should do if, for instance, ActiveProgression is a transient service? How can I create SubcategoryView in this case?
The idea of putting extra parameters in Create() seems quite bad, but it also seems the only solution in this case.
CategoryViewFactory'sCreatemethod acts as a Composer. A Composer is part of your application's Composition Root that is responsible for composing instances. In this case theCreatemethod is using Pure DI rather can moving that responsibility to a DI Container.As long as
CategoryViewFactoryis defined in the application's startup path, a.k.a. the Composition Root, everything what you're doing is perfectly fine. It's even fine forActiveProgressionto call back into the DI Container, *as long asActiveProgressionis part of the Composition Root as well. WhenActiveProgressionis defined outside the context of the Composition Root, it's use of the DI Container can be considered a Service Locator, which is a well-known anti-pattern.As long as
CategoryViewFactoryis transient as well, there will be no problem. WhenCategoryViewFactoryis singleton, however,ActiveProgressionwill become a Captive Dependency.Although, what you're doing is perfectly fine, it might be less obvious for
CategoryViewFactoryto use Pure DI, while other parts of your Composition root use a DI Container. You can considerCategoryViewFactoryto forward the responsibility of composition to the DI Container. For instance:Notice how in this case, the
Categoryruntime data is not supplied any longer to the constructor of the created views. This simplifies the creation of those objects, because their construction no longer depends on the existence of runtime data, which is a good practice. This also requires changing yourICategoryView.