c# - Implementación de patrón de escalera.
.net decoupling (3)
Encontré la descripción del patrón "Escalera" en el libro "Código adaptativo a través de C #" y realmente no entiendo cómo se supone que se debe implementar esto:
( source )
Así que tengo el montaje del cliente:
using ServiceInterface;
namespace Client
{
class Program
{
static void Main(string[] args)
{
// Have to create service implementation somehow
// Where does ServiceFactory belong?
ServiceFactory serviceFactory = new ServiceFactory();
IService service = serviceFactory.CreateService();
service.Do();
}
}
}
Montaje de la interfaz de servicio:
namespace Service
{
public interface IService
{
void Do();
}
}
Y montaje de implementación de servicios:
using ServiceInterface;
namespace ServiceImplementation
{
public class PrintService : IService
{
public void Do()
{
Console.WriteLine("Some work done");
}
}
}
Y la pregunta es: ¿cómo obtengo un objeto IService
en el espacio de nombres del Client
? ¿Dónde debo colocar la creación del objeto new PrintService()
real? Esto no puede ser parte de ServiceInterface
, porque el ensamblaje de la interfaz no depende de ServiceImplementation
. Pero tampoco puede ser parte de Client
o ServiceImplementation
porque Client
solo debe depender de ServiceInterface
.
La única solución a la que llegué es tener el ensamblaje de la Application
, que tiene referencias a los tres ( Client
, ServiceInterface
y ServiceImplementation
) e inyecta IService
en el Client
. ¿Me estoy perdiendo de algo?
En ese caso, el proyecto del Client
debe contener referencias tanto a Service
como a ServiceImplementation
. Esas referencias se utilizarán solo para crear un contenedor IoC que se utilizará como DI. Al inicio de la aplicación, debe registrar todas las implementaciones de interfaz en el contenedor IoC.
Si implementará ServiceImplementation
contra Service
interfaz del Service
y codificará el Client
según la Interfaz del Service
, no habrá dependencia en la ServiceImplementation
del ServiceImplementation
.
También puede ver cómo se implementa el patrón de escalera en las muestras para "Código adaptativo a través de C #":
https://github.com/garymcleanhall/AdaptiveCode/tree/master/Sprints/sample-sprint2-markdown
Lo pondría en el ServiceFactory
. Necesita algún parámetro, por ejemplo, pasado en el constructor de fábrica o recuperado de la configuración, etc., que determina qué implementación de servicio de IService
es creada por la fábrica.
Los puntos de entrada de la aplicación deben ser la raíz de la composición, según el excelente libro de Mark Seemann sobre la inyección de dependencia. Aquí, el problema es más sobre la inversión de dependencia, por lo que tanto el cliente como la implementación deben depender de las abstracciones.
Lo que el diagrama no muestra, pero es de esperar que otras partes del libro quede claro, es que el punto de entrada hará referencia natural y necesariamente a todo lo que se necesita para construir cualesquiera que sean sus raíces de resolución (controladores, servicios, etc.). Pero esto es El único lugar que tiene tal conocimiento.
Tenga en cuenta que a veces es correcto que los clientes sean "propietarios" de las interfaces de las que dependen: la interfaz que ISecurityService
puede vivir en el ensamblaje de los Controllers
, el IUserRepository
puede estar en el ensamblado de ServiceImplementations
, etc. Esto no es práctico cuando> 1 cliente necesita acceso a la interfaz, por supuesto.
Si sigue SOLID, naturalmente encontrará que la inyección de dependencia es una necesidad, pero los contenedores de inversión de control son menos prioritarios. Me encuentro usando Pure Dependency Injection (construcción manual de raíces de resolución) cada vez más a menudo.