La terminología de la pregunta realmente no coincide con el código de ejemplo. El Ambient Contextes un patrón utilizado para tomar una dependencia de cualquier clase en cualquier módulo de la manera más fácil posible, sin contaminar cada clase para aceptar la interfaz de la dependencia, pero manteniendo la idea de inversión de control. Dichas dependencias generalmente se dedican al registro, la seguridad, la administración de sesiones, las transacciones, el almacenamiento en caché, la auditoría, por lo que cualquier preocupación transversal en esa aplicación. Es de alguna manera molesto para añadir una ILogging, ISecurity, ITimeProvidera los constructores y la mayoría de las veces no todas las clases necesitan, todo al mismo tiempo, por lo que entiendo su necesidad.
¿Qué pasa si la vida útil de la ISessioninstancia es diferente a la de la instancia ILogger? Tal vez la instancia de ISession debería crearse en cada solicitud y el ILogger una vez. Por lo tanto, tener todas estas dependencias gobernadas por un objeto que no es el contenedor en sí mismo no parece la opción correcta debido a todos estos problemas con la administración y localización de por vida y otros descritos en este hilo.
El IAmbientContexten la pregunta no resuelve el problema de no contaminar a todos los constructores. Todavía tiene que usarlo en la firma del constructor, claro, solo una vez esta vez.
Entonces, la forma más fácil NO es usar la inyección de constructor o cualquier otro mecanismo de inyección para tratar dependencias transversales, sino usar una llamada estática . En realidad, vemos este patrón con bastante frecuencia, implementado por el propio marco. Verifique Thread.CurrentPrincipal, que es una propiedad estática que devuelve una implementación de la IPrincipalinterfaz. También es configurable para que pueda cambiar la implementación si lo desea, por lo que no está acoplado a ella.
MyCore ahora se ve algo así como
public class MyCoreClass
{
public void BusinessFeature(string data)
{
LoggerContext.Current.Log(data);
_repository.SaveProcessedData();
SessionContext.Current.SetData(data);
...etc
}
}
Este patrón y las posibles implementaciones han sido descritas en detalle por Mark Seemann en este artículo . Puede haber implementaciones que se basan en el contenedor de IoC que usted usa.
Desea evitar AmbientContext.Current.Logger, AmbientContext.Current.Sessionpor los mismos motivos descritos anteriormente.
Pero tiene otras opciones para resolver este problema: use decoradores, intercepción dinámica si su contenedor tiene esta capacidad o AOP. El contexto ambiental debería ser el último recurso debido al hecho de que sus clientes ocultan sus dependencias a través de él. Todavía usaría Contexto ambiental si la interfaz realmente imita mi impulso de usar una dependencia estática como DateTime.Nowo ConfigurationManager.AppSettingsy esta necesidad surge con bastante frecuencia. Pero al final, la inyección del constructor podría no ser una mala idea para obtener estas dependencias ubicuas.
IServiceusa para comunicarse con otros servicios? SiIServicerepresenta una vaga dependencia de otros servicios, entonces suena como un localizador de servicios y no debería existir. Su clase debería depender de interfaces que describan explícitamente qué hará su consumidor con ellas. Ninguna clase necesita un servicio para proporcionar acceso a un servicio. Una clase necesita una dependencia que hace algo específico que necesita la clase.