3

Solution projects:

  • ClassLibrary.Abstract
    • has lots of yummy services
  • ClassLibrary.Concrete
    • contains implementations to services above
  • MvcWebApp
    • references classes above
    • contains composition root

Everything is registered in the composition root, so MvcWebApp obviously references container, in my case it's Autofac but I don't suppose it matters.

Question: What is the proper way (if there's any) to resolve services at runtime in the class libraries without adding references to the container everywhere in the solution, while still being able to control lifetime scope?

Luis Ferrao
  • 1,463
  • 2
  • 15
  • 30
  • Can you elaborate on why you need to resolve an instance lazily? – Steven Jan 19 '17 at 14:19
  • See [Why do we need Abstract factory design pattern?](http://stackoverflow.com/a/2280289/181087) – NightOwl888 Jan 19 '17 at 16:23
  • @steven actions triggered by the UI will use different services (like lego blocks) depending on parameters – Luis Ferrao Jan 20 '17 at 06:35
  • @NightOwl888 thanks, but I was thinking of something more generic than creating a factory for all these services. The class library is full of these services (lego blocks) meant to be resolved and released at runtime depending on the job parameters. – Luis Ferrao Jan 20 '17 at 06:49
  • A big warning about factories: [they are a code smell](https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=100). – Steven Jan 20 '17 at 07:15
  • Please update your question with a concrete example of when you need this. – Steven Jan 20 '17 at 07:16
  • @steven I can do that, but I fear if you ask it's because my question is not clear enough. Containers such as Autofac offer methods like `using (var scope = beginLifetimeScope()) { var service = scope.Resolve(); service.DoSomething(); }`. Basically I want to know if this can happen inside a class library without referencing the DI container itself. The class library is aware that it's resolving something that has a lifetime scope, but it seems to me it doesn't need to know that it's Autofac. i.e Autofac's scoped dependency resolever could implement a BCL interface with resolve method – Luis Ferrao Jan 20 '17 at 08:49
  • Without something to go to to get instances lazily (Service Locator), how would libraries get the instances without simple injection? You *could* have an abstract locator instead of knowing about Autofac; but my experience is that the complexity that adds defeats the purpose of using a DI container. – Peter Ritchie Jan 25 '17 at 14:47

1 Answers1

0

If a service needs a sub-service-implementation

  • the service can create the sub-service itself
    • (a) by calling the concrete constructor of the subservice (no ioc/di)
    • (b) by asking the container to do it.
    • (c) there is some factory or service-locator that the service can ask.
  • (d) the service-constructor has parameters/properties for the required sub-service. There is one initialisation module that wires up all needed services by calling the constructors with the parameters.

your question: is it possible to avoid (b)?

If it is important to lazy resolve at runtime you have to do (c)

I prefer (d) but this is not lazy loading.

you want your lib to create the service on itself and the lib should not have a reference to your ioc-container autofac.

so you have to hide autofac behind a factoryInterface with methods createService<T> and releaseService<T>

lib knows the interface

your factoryClass implements factoryInterface using autofac.

k3b
  • 14,517
  • 7
  • 53
  • 85