unity inyeccion gavilanch2 dependencias asp.net-mvc dependency-injection structuremap httpcontext

asp.net-mvc - gavilanch2 - inyeccion de dependencias python



ASP.NET MVC: HTTPContext e Inyección de Dependencia (4)

Actualmente tengo un ActionFilter que obtiene el nombre de los usuarios actuales de HttpContext y lo pasa a la acción que lo usa en un método de servicio. p.ej:

Service.DoSomething(userName);

Ahora tengo una razón para hacer esto no en el nivel de acción sino en el nivel de constructor del controlador. Actualmente estoy usando el mapa de estructura para crear controladores e inyectar el servicio. Estoy viendo algo así como:

public interface IUserProvider { string UserName { get; } } public class HttpContextUserProvider : IUserProvider { private HttpContext context; public HttpContextUserProvider(HttpContext context) { this.context = context; } public string UserName { get { return context.User.Identity.Name; } } }

Dicho esto, mi foo de IoC es muy débil ya que es el primer proyecto en el que lo he usado.

Entonces mi pregunta es ... ¿cómo puedo decirle a la estructura del mapa que pase en HttpContext en el constructor para HttpContextUserProvider? Esto parece extraño ... No estoy seguro de cómo pensar en HttpContext.


No estoy seguro de por qué te estás molestando. Parece que solo usar HttpContext.Current directamente en HttpContextUserProvider es lo correcto. Nunca vas a sustituir en un HttpContext diferente ...


Parece que debería usar HttpContextBase lugar de HttpContextUserProvider . Esta es una abstracción original de HttpContext y le permite crear un simulacro, escribir UnitTests e inyectar sus dependencias.

public class SomethingWithDependenciesOnContext { public SomethingWithDependenciesOnContext(HttpContextBase context) { ... } public string UserName { get {return context.User.Identity.Name;} } } ObjectFactory.Initialize(x => x.For<HttpContextBase>() .HybridHttpOrThreadLocalScoped() .Use(() => new HttpContextWrapper(HttpContext.Current));


Tal vez dejé algo, pero la respuesta anterior no funciona para mí (se ha eliminado desde entonces, aunque seguía siendo una respuesta útil), mostró cómo decirle a SM que pase los argumentos del constructor. En cambio si lo hago:

ObjectFactory.Initialize(x => { x.BuildInstancesOf<HttpContext>() .TheDefault.Is.ConstructedBy(() => HttpContext.Current); x.ForRequestedType<IUserProvider>() .TheDefault.Is.OfConcreteType<HttpContextUserProvider>(); });

Lo hago funcionar. Hice esto después de encontrar: http://codebetter.com/blogs/jeremy.miller/archive/2008/03/20/if-you-need-something-in-structuremap-but-you-can-t-build- it-with-new.aspx

editar:

Gracias a la respuesta de Brad creo que tengo un mejor manejo de HttpContext. Su respuesta definitivamente funciona, simplemente no estoy seguro de que me guste tener la llamada a HttpContext.Current dentro de una clase (parece que oculta la dependencia, pero estoy lejos de ser un experto en esto).

El código anterior debería funcionar para inyectar HttpContext por lo que yo sé. Matt Hinze menciona el punto agregado de que si todo lo que necesito de HttpContext es User.Identity.Name, mi diseño debe ser explícito al respecto (tener una interfaz alrededor de HttpContext solo expone lo que necesito). Creo que es una buena idea.

La cuestión es que durante el almuerzo me di cuenta de que mi servicio realmente solo necesita depender de una cadena: userName. Tenerlo depender de IUserProvider podría no tener mucho valor agregado. Así que sé que no quiero que dependa de HttpContext, y sé que todo lo que necesito es una cadena (userName) - Necesito ver si puedo aprender lo suficiente de StructureMap para hacer esta conexión por mí. (La respuesta de sirrocoo da una pista sobre dónde comenzar, pero la eliminó: * ().


Tener una interfaz abstracta HttpContext.Current. Exponga solo los métodos que necesita. GetUserName() llamaría a HttpContext.Current.User.Identity.Name en la implementación, por ejemplo. Hazlo lo más delgado posible.

Tome esa abstracción e inyéctela en su otra clase de proveedor. Esto le permitirá probar al proveedor burlándose de la abstracción de contexto http. Como beneficio adicional, puedes hacer otras cosas ingeniosas con esa abstracción de HttpContext además de burlarlo. Reutilizarlo, por un lado. Agregue params de tipo genérico a los bolsos, etc.