Inyección de dependencia WCF y fábrica abstracta.
dependency-injection factory-pattern (2)
Tengo este método wcf
Profile GetProfileInfo(string profileType, string profileName)
y una regla de negocio:
si profileType es "A" leído desde la base de datos.
si profileType es "B" leído desde un archivo xml.
La pregunta es: ¿cómo implementarlo utilizando un contenedor de inyección de dependencias?
Gran respuesta por Mark, sin embargo, la solución dada no es la fábrica abstracta, sino la implementación del patrón de fábrica estándar. Compruebe cómo encajan las clases de Marks en el diagrama UML del patrón de fábrica estándar. Haga clic aquí para ver las clases anteriores aplicadas a Factory pattern UML
Como en Factory pattern, la fábrica conoce las clases concretas, podemos simplificar el código de ProfileRepositoryFactory
como se muestra a continuación. El problema de inyectar los diferentes repositorios a la fábrica es que tiene más cambios de código cada vez que agrega un nuevo tipo concreto. Con el siguiente código, solo tiene que actualizar el interruptor para incluir una nueva clase concreta
public class ProfileRepositoryFactory : IProfileRepositoryFactory
{
public IProfileRepository Create(string profileType)
{
switch(profileType)
{
case "A":
return new DatabaseProfileRepository();
case "B":
return new XmlProfileRepository();
}
}
}
Abstract Factory es un patrón más avanzado que se usa para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas. El diagrama de clases de UML disponible here explica bien.
Primero asumamos que tienes un IProfileRepository algo como esto:
public interface IProfileRepository
{
Profile GetProfile(string profileName);
}
así como dos implementaciones: DatabaseProfileRepository
y XmlProfileRepository
. El problema es que le gustaría elegir el correcto en función del valor de profileType.
Puedes hacer esto introduciendo este Abstract Factory :
public interface IProfileRepositoryFactory
{
IProfileRepository Create(string profileType);
}
Suponiendo que se haya inyectado IProfileRepositoryFactory en la implementación del servicio, ahora puede implementar el método GetProfileInfo de esta manera:
public Profile GetProfileInfo(string profileType, string profileName)
{
return this.factory.Create(profileType).GetProfile(profileName);
}
Una implementación concreta de IProfileRepositoryFactory podría tener este aspecto:
public class ProfileRepositoryFactory : IProfileRepositoryFactory
{
private readonly IProfileRepository aRepository;
private readonly IProfileRepository bRepository;
public ProfileRepositoryFactory(IProfileRepository aRepository,
IProfileRepository bRepository)
{
if(aRepository == null)
{
throw new ArgumentNullException("aRepository");
}
if(bRepository == null)
{
throw new ArgumentNullException("bRepository");
}
this.aRepository = aRepository;
this.bRepository = bRepository;
}
public IProfileRepository Create(string profileType)
{
if(profileType == "A")
{
return this.aRepository;
}
if(profileType == "B")
{
return this.bRepository;
}
// and so on...
}
}
Ahora solo necesita obtener su contenedor DI para cablearlo todo para usted ...