Después de leer esta publicación puedo entiendo las diferencias entre AddTransient, AddScoped y AddSingleton sin embargo, no puedo ver el uso práctico de cada uno de ellos.

Mi entendimiento es

AddTransient

Crea una nueva instancia cada vez que el cliente la solicita.

services.AddTransient<IDataAccess, DataAccess>();

Devolverá un nuevo objeto DataAccess cada vez que un código de cliente lo solicite. Más probablemente un constructor.

Uso de AddTransient

En los casos en que tengamos que acceder a una base de datos para leerla, actualizarla y destruir el objeto de acceso (DataAccess), es mejor usar AddTransient: no estoy seguro acerca de la seguridad del subproceso.

AddScoped

Crea una nueva instancia para cada solicitud web http.

Uso de AddScoped

 services.AddScoped<ShoppingCart>(serviceProvider => ShoppingCart.GetShoppingCart(serviceProvider));

Esto significa que cada solicitud web tendrá su propia instancia de carrito de compras, lo que significa que cada usuario / cliente tendrá su propia instancia de carrito de compras para esa solicitud web http.

AddSingleton

Cree una instancia única para todas las solicitudes web http.

Uso de AddSingleton

Encontré este código en una aplicación de muestra, pero no entiendo cómo está siendo útil.

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 

¿Alguien puede dar un ejemplo práctico decente cuando usar AddSingleton y verificar si mi comprensión de AddTransient y AddScoped es correcta?

17
Yawar Murtaza 5 mar. 2017 a las 16:28

2 respuestas

La mejor respuesta

Su comprensión de los 3 ámbitos es correcta.

Transitorio se usaría cuando el componente no se pueda compartir. Un objeto de acceso a la base de datos no seguro para subprocesos sería un ejemplo.

Alcance se puede utilizar para contextos de base de datos de Entity Framework. La razón principal es que las entidades obtenidas de la base de datos se adjuntarán al mismo contexto que ven todos los componentes de la solicitud. Por supuesto, si planea hacer consultas con él en paralelo, no puede usar Scoped.

Otro ejemplo de un objeto con ámbito sería algún tipo de clase RequestContext, que contiene p. El nombre de usuario de la persona que llama. Un filtro de middleware / MVC puede solicitarlo y completar la información, y otros componentes en el futuro también pueden solicitarlo, y seguramente contendrá la información para la solicitud actual.

Los componentes Singleton se comparten siempre, por lo que son mejores para componentes seguros para subprocesos que no necesitan estar vinculados a una solicitud. Un ejemplo sería IOptions, que da acceso a la configuración. Una clase de contenedor HttpClient que usa SendAsync en una sola instancia estática HttpClient también sería completamente segura para subprocesos, y un buen candidato para ser Singleton.

Tenga en cuenta que si tiene un componente Singleton que depende de un componente Scoped, su dependencia se eliminaría antes. Por lo tanto, un componente no puede depender de otro componente que tenga un alcance menor que él mismo.

17
juunas 6 mar. 2017 a las 07:12

He visto la vista "solo usar AddTransient<T>()", pero no estoy de acuerdo.

Piensa en la asignación de memoria

Odio asignar cosas cuando no tengo que hacerlo, así que si sé que estoy creando algo que es seguro para subprocesos, o que tengo documentación explícita de que tener una instancia de singleton es el uso esperado, entonces estoy creando un singleton.

AddSingleton ()

Aquí está la instancia de ApplicationInsights TelemetryClient como singleton. Su documentación dice que esto funciona.

telemetryClient = new TelemetryClient(TelemetryConfiguration.Active);
services.AddSingleton<TelemetryClient>(telemetryClient);

En este proyecto, también uso Azure Table Storage, y descubrí que crear un CloudTableClient como singleton funciona bien. No necesito seguir creando instancias para cada solicitud.

CloudStorageAccount storageAccount = CloudStorageAccount.Parse(Configuration.GetValue<string>("storageAccountConnectionString"));
CloudTableClient someTableClient = storageAccount.CreateCloudTableClient();
services.AddSingleton<CloudTableClient>(someTableClient);

En cierto sentido, es el equivalente de la propiedad estática de solo lectura de una clase, por ejemplo:

public static readonly CloudTableClient cloudTableClient = new CloudTableClient(...);

... solo hay una instancia en toda la aplicación, pero al usar services.AddSingleton<T>() obtenemos acceso directo a ella usando la Inyección de dependencia.

AddScoped ()

Un ejemplo de AddScoped<T>() para mí es que quiero insertar el JavaScript que necesito para obtener Application Insights en una página web, pero uso Content-Security-Policy, así que necesito poner un nonce en cualquier JavaScript de la página . Tengo un poco de código que me ayuda a hacerlo.

services.AddScoped<ApplicationInsightsJsHelper>();

AddTransient ()

Todavía no he encontrado la necesidad de usar AddTransient<T>() para nada. Puede ser que no piense en las cosas que he creado cada vez que las necesito como "servicios" ... son solo variables que inventé. En cierto sentido, AddTransient<T>() es un uso oculto del patrón Factory ... en lugar de llamar a una función estática MyServiceFactory.Create(), tienes que Inyección de dependencia (efectivamente) hace lo mismo por ti.

1
Scott 22 may. 2019 a las 22:03