Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

338
Vistas
How to allow for optional services with Microsoft.Extension.DependencyInjection?

I am playing around with ASP.NET Core on my own hobby project, I want to create a framework that will be consumed by a developer, and I want to allow optional service and use defaults if they are not registered.

I am getting the Unable to resolve service for type 'XXX' error, but I would prefer the DI to return null rather then throw an exception. I want to allow for optional services, so if a service is found, use that in the constructor, if not found, pass null into the constructor.

In my implementation I have:

public IServiceManager(IService service, ...)
{
    _service = service ?? new DefaultService();
    ...
}

So as you can see, if the service cannot be found (null) use the default. Perhaps I am misunderstanding how DI works. Perhaps I could use a factory to do this instead? However, in my system I using default services when non is provided will be a common occurrence, so I need a solution that doesn't require the consumer of the API to register a service.

Is there a way to configure ASP.NET Core DI to return null rather then throw an exception?

about 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Add default value to that parameter in the constructor.

public IServiceManager(IService service = null, ...)
{
  _service = service ?? new DefaultService();
  ...
}
about 4 years ago · Santiago Trujillo Denunciar

0

By their very nature, constructor injection is always considered as mandatory.

The very first versions of the Microsoft DI (I don't like using the term ASP.NET Core DI, because it does not depend on ASP.NET Core and can be used outside of it) only supported the constructor with the most parameters.

I think this has been changed since then to allow multiple constructors and the IoC container will choose a fitting one. That being said, you'd likely need to define multiple constructors.

public IServiceManager(IService service, IOtherService otherService)
{
}

public IServiceManager(IOtherService otherService)
{
}

Then the second constructor should be called, if IService isn't registered with the IoC container.

But it's still quite a questionable practice at best and makes your code harder to maintain and hold its invariant/loose coupling.

You should never have to instantiate your types inside your services, not even for optional services.

Instead, you should provide registrations which allow a user to override them with their own implementations.

public static IServiceCollection AddMyLibrary(this IServiceCollection services)
{
    services.TryAddTransient<IService, Service>();
    services.TryAddTransient<IOtherService, OtherService>();
}

Then the user override it.

services.AddTransient<IService, CustomService>();
services.AddMyLibrary();

Now CustomService will be injected where IService is requested.

about 4 years ago · Santiago Trujillo Denunciar

0

Easiest would be to register the DefaultService component itself for the IService service within your IoC container - I'm using the terminology of Castle Windsor. Most of the containers allow to register multiple components for a service. In case you do not register a custom component for the service (another implementation of IService), DefaultService will be resolved and injected; otherwise your custom component will be resolved for the service, just register the components in proper order (in Castle Windsor, the component registered first will be considered: multiple components for a service)

WindsorContainer container = new WindsorContainer();

container.Register(Component.For<IServiceManager>().ImplementedBy<ServiceManager>());
container.Register(Component.For<IService>().ImplementedBy<CustomService>());
container.Register(Component.For<IService>().ImplementedBy<DefaultService>());

IServiceManager serviceManager = container.Resolve<IServiceManager>();
IService service = ((ServiceManager)serviceManager).Service; // service is of type CustomService

Regarding the comment below from @Tseng:

This beats the idea of having Dependency Injection / IoC container in the firstplace, when you instantiate it inside the constructor

It is not always the case... If you have an optional dependency, first, define it as a property with a public setter, so component can be injected if registered. In case there is no component registered (thus property is not set by the container), I think it can be acceptable to instantiate the default component via the "dangerous" new keyword. Everything is context-dependent - to be clear, I wouldn't instantiate a service manually, but there are always exceptions.

about 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda