tutorial que net mvc microservicios example ejemplos crear c# dependency-injection simple-injector

c# - net - signalr que es



Cómo configurar el contenedor de inyector simple y lifestylse en una aplicación web MVC con WebAPI, WCF, SignalR y Tarea de fondo (2)

Tengo que decir que me tropecé con un escenario similar hace algún tiempo, terminé por compartir mi configuración sobre mi API web y señalR, pero necesita implementar un estilo de vida personalizado para signalR ya que no está basado en la solicitud web.

especialmente en signalR encontrará algunos problemas manejando dependencias de solicitud por web en un Hub, algunos de ellos serán nulos, como httpContext.Current entre otros.

La solución:

Necesita un estilo de vida híbrido entre WebRequestLifestlye y Lifestyle.Transient, Lifestyle.Singleton o LifetimeScopeLifestyle. Terminé terminé de usar el patrón decorador, puede leer esta publicación y esta otra publicación .

mi decorador

public class CommandLifetimeScopeDecorator<T> : ICommandHandler<T> { private readonly Func<ICommandHandler<T>> _handlerFactory; private readonly Container _container; public CommandLifetimeScopeDecorator( Func<ICommandHandler<T>> handlerFactory, Container container) { _handlerFactory = handlerFactory; _container = container; } public void Handle(T command) { using (_container.BeginLifetimeScope()) { var handler = _handlerFactory(); // resolve scoped dependencies handler.Handle(command); } } } public interface ICommandHandler<in T> { void Handle(T command); }

Administre las dependencias usando un activador concentrador para signalR

public class MyHubActivator : IHubActivator { private readonly Container _container; public MyHubActivator(Container container) { _container = container; } public IHub Create(HubDescriptor descriptor) { return _container.GetInstance(descriptor.HubType) as IHub; } }

un archivo raíz compuesto que es donde va a manejar sus dependencias

public CompositRoot(Container container) { _container = container; } public container Configure() { // _container.Registerall container dependencies return _container; }

luego comparte tu configuración de raíz compuesta cuando estás iniciando tu aplicación

var compositRoot = new CompositRoot(simpleInjector.Container); //simple injector instance compositRoot.Configure();

Para signalR

GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => new MyHubActivator(compositRoot));

¡y puede reutilizar su configuración entre otros proyectos!

¡Mis dos centavos esperan que eso ayude!

La documentación del inyector simple proporciona excelentes ejemplos sobre cómo configurar el contenedor para WebRequest, Web API, WCF, ... pero los ejemplos son específicos de una tecnología / estilo de vida a la vez. ¡Nuestra aplicación web usa la mayoría de ellos juntos! No tengo claro cómo configurar el contenedor para que funcione con varios estilos de vida.

Digamos que tengo un proyecto de MVC con API web. Tengo los siguientes objetos:

  • MyDbContext: mi código de entidad primer contexto db
  • IMyDataProvider implementado por MyDataProvider: contiene lógica de consulta y usa MyDbContext
  • MyController: controlador MVC que usa IMyDataProvider
  • MyApiController: Controlador WebApi que usa IMyDataProvider

¿Debo crear y configurar un contenedor para cada tipo de estilo de vida?

Cuando registro todo con RegisterPerWebRequest<T> funciona en ambos tipos de controladores. ¿Esto es seguro? ¿O me encontraré con problemas al usar async / await en un controlador Web API?

¿Cuál es la mejor configuración cuando tengo controladores MVC y Web API que se inyectan las mismas instancias?

¿Debería usar un estilo de vida híbrido?

Ahora, para complicar las cosas ... nuestra aplicación también utiliza tareas en segundo plano y SignalR.

Ambas cosas ocurrirán a veces fuera de una WebRequest y necesitarán acceso a los mismos objetos que se describen arriba.

La mejor solución sería usar un alcance Lifetime?

¿Tendría que crear un nuevo contenedor para ese estilo de vida? o puedo reutilizar / reconfigurar mi contenedor de MVC / API web?

¿Hay un estilo de vida triple?


Por lo general, no necesita tener un contenedor por estilo de vida; En general, desea tener una instancia de contenedor por Dominio de aplicación. Sin embargo, mezclar Web API en el mismo proyecto con MVC es desde el punto de vista arquitectónico una idea horrible IMO (como se explica aquí , aquí y aquí ). Entonces, en caso de que separes esas partes en sus propios bloques arquitectónicos, ya tendrás menos problemas.

Pero en caso de que esté ejecutando MVC y API Web en el mismo proyecto, esto básicamente significa que siempre estará utilizando la API web. El WebApiRequestLifestyle se creó explícitamente para funcionar:

bien tanto dentro como fuera de IIS. es decir, puede funcionar en un proyecto de API web alojado en uno mismo donde no hay HttpContext.Current. ( fuente )

En general, es seguro usar WebRequestLifestyle en caso de que solo esté ejecutando en IIS cuando no tiene la intención de girar las operaciones paralelas usando ConfigureAwait(false) (que debería ser realmente raro IMO) como se explica aquí .

Entonces, si todavía está mezclando la API web con MVC en el mismo proyecto, no hay razón para usar un estilo de vida híbrido ; simplemente puede usar el mismo estilo de vida. Sin embargo, para hacer un procesamiento en segundo plano, es posible que necesites construir un estilo de vida híbrido, pero cada escenario necesita un híbrido diferente. Sin embargo, los híbridos se pueden acumular y puede crear fácilmente un "estilo de vida triple" si es necesario.

Dado que desea hacer un procesamiento en segundo plano con SignalR, debe decidir en qué tipo de estilo de vida se enfoca para ejecutar esas operaciones en segundo plano. El estilo de vida más obvio es el LifetimeScopeLifestyle, lo que significa que debe realizar sus registros con el siguiente estilo de vida:

var hybridLifestyle = Lifestyle.CreateHybrid( lifestyleSelector: () => HttpContext.Current != null, trueLifestyle: new WebRequestLifestyle(), falseLifestyle: new LifetimeScopeLifestyle());

Sin embargo, un alcance de por vida debe comenzarse explícitamente (como fue el alcance de la solicitud web que se inicia implícitamente para usted si incluye el SimpleInjector.Integration.Web.dll en su aplicación web). Cómo hacer esto depende de su diseño, pero este q / a sobre SignalR podría apuntarle en la dirección correcta.