Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 18 de enero de 2022
.NET

Versiones de .NET anteriores a la 6 no disponían de una fórmula específica para determinar si un tipo o interfaz está registrado como servicio en el sistema de inyección de dependencias.

La única forma de hacerlo era intentar resolverlo, usando métodos como GetService() o GetService<T>(), y comprobar si el resultado era null:

var myService = serviceProvider.GetService<IMyService>();
if(myService is null)
{
    // El servicio no está registrado, hacemos algo
}

¿Cuál es el inconveniente de esto? Si el servicio no está registrado, ninguno: la llamada retornará un nulo y listo. 

El problema viene cuando sí está registrado, pues estaremos forzando la resolución de un servicio que, en realidad, no necesitamos para nada, pues sólo nos interesaba saber si existía o no. Porque recordemos que la resolución de un servicio podría tener un coste importante en términos de rendimiento, memoria, o incluso efectos colaterales en el estado de la aplicación, especialmente si nuestro servicio depende de otros, que a su vez dependen de otros, etc.

Para simplificar este escenario y hacer más sencilla la implementación de métodos muy flexibles, como los requeridos para las minimal APIs, .NET 6 ha introducido el nuevo servicio IServiceProviderIsService (¡curioso nombre!), cuyo objetivo es proporcionar un mecanismo sencillo para determinar si un tipo de servicio está registrado y accesible a través de un IServiceProvider, pero sin forzar su resolución.

public interface IServiceProviderIsService
{
    bool IsService(Type serviceType);
}

La forma de uso es muy sencilla. Basta con obtener una instancia de IServiceProviderIsService y utilizar su método IsService() para determinar si será posible obtener un servicio a través del inyector de dependencias.

public class Foo
{
    public Foo(IServiceProviderIsService spis)
    {
        if (!spis.IsService(typeof(IMyInterface)))
        {
            // El servicio no está registrado
        }
    }
}

El uso de este servicio no será muy habitual en nuestras aplicaciones; de hecho, lo más probable es que jamás tengamos que utilizarlo en aplicaciones convencionales. Pero si programamos frameworks, APIs o componentes vale la pena saber que este mecanismo está ahí, por si acaso ;)

Publicado en Variable not found.

2 Comentarios:

MontyCLT dijo...

No creo que su utilidad sea destinada únicamente a frameworks o similares, incluso en aplicaciones con un mínimo de modularidad, donde cierta funcionalidad venga dada por plugins que implementen interfaces del core, esto puede ser muy útil.

Un sencillo ejemplo, típica aplicación de facturación modular, que mediante una serie de plugins puedan modificar el comportamiento para generar el número de factura, y lo hagan implementando una interfaz del core llamada IInvoiceCodeGenerator o similar.

Poder comprobar que la interfaz IInvoiceCodeGenerator está registrada es útil para avisar al usuario de que antes de proceder a generar las facturas, debe de instalar un plugin del catálogo que genera los códigos de acuerdo a las normas de cada país.

José María Aguilar dijo...

Hola!

Sí, tienes razón, quizás en esos escenarios también pueda resultar interesante. Al final, las herramientas están ahí, es cuestión de encontrarles su hueco ;)

Saludos & gracias por comentar!