Question

Is there a way, using StructureMap (the Dependency Injection container) to inject a specific instance of a type into all types from a given namespace that are requesting that type?

Here is an example set up:

EmployeesDbContext : IAbstractDbContext { ... }
AccountingDbContext : IAbstractDbContext { ... }
MarketingDbContext : IAbstractDbContext { ... }

StructureMap registers all of these types against IAbstractDbContext as expected.

Then:

  • HumanResources.Domain which has business logic and entities related to the Employees database, therefore requiring the EmployeesDbContext
  • Accounting.Domain which has business logic and entities related to the Accounting database, therefore requiring the AccountingDbContext
  • etc...

I then have a WebUI (ASP.NET MVC) project, which can be thought of as the composition root, which is leveraging StructureMap which will compose the dependency trees.

It makes the most sense to leverage the fact that the DbContext requirement is largely driven by the namespace consuming it.

Trouble is, I'm not sure how to tackle this set up, any thoughts much appreciated!

Was it helpful?

Solution

When you have a single abstraction IAbstractDbContext it implies that all implementations are interchangable. However, it's very unlikely that you will be able to swap them, since some consumers expect to work with the Employees data model, while others expect to work with the Marketing model. Because of this you are violating the Liskov substitution principle.

Instead you should define an abstraction per model. For instance: IEmployeesDbContext, IAccountingDbContext and IMarketingDbContext. Doing this resolves the ambiguity in your design that is causing you trouble. This makes it much easier to understand what data model a consumer needs, and allows you to simplify the registration process, since you don't need any conditional registrationd anymore.

OTHER TIPS

As noted in my comment, Steven's answer is likely correct.

As far as I know, it's not directly possible to resolve a dependency based on the consumer's namespace. However, you may be able to get there using named instances and reflection. I would recommend taking this approach--you are better off creating explicit named instances and resolving to them directly through a factory.

In a nutshell:

  • Register named instances of your IAbstractDbContext by namespace
  • Create an IDbContextFactory class with one method: IAbstractDBContext Create(string namespace). Have the implementation wrap the container instance and resolve via the string parameter.
  • Inject the factory in the constructor of the consuming class
  • Use reflecting to get the namespace of the consuming class, and then use the factory to create your DbContext instance, passing the namespace as a parameter.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top