2010-01-30 9 views
18

que tienen este método WCFinyección WCF La dependencia y la fábrica de resumen

Profile GetProfileInfo(string profileType, string profileName) 

y una regla de negocio:

si profileType por es "A" leer de la base de datos.

if profileType es "B" leída del archivo xml.

La pregunta es: ¿cómo implementarlo usando un contenedor de inyección de dependencia?

Respuesta

22

primero vamos a suponer que usted tiene un algo IProfileRepository así:

public interface IProfileRepository 
{ 
    Profile GetProfile(string profileName); 
} 

así como dos implementaciones: DatabaseProfileRepository y XmlProfileRepository. El problema es que le gustaría elegir el correcto según el valor de profileType.

Usted puede hacer esto mediante la introducción de este Abstract Factory:

public interface IProfileRepositoryFactory 
{ 
    IProfileRepository Create(string profileType); 
} 

Suponiendo que el IProfileRepositoryFactory ha sido inyectado en la implementación del servicio, ahora se puede poner en práctica el método GetProfileInfo así:

public Profile GetProfileInfo(string profileType, string profileName) 
{ 
    return this.factory.Create(profileType).GetProfile(profileName); 
} 

Una implementación concreta de IProfileRepositoryFactory podría verse así:

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 sólo tiene que conseguir su contenedor de DI de elección de unirlo todo por ti ...

+0

Esos 'sis' secuenciales podrían ser reemplazados por un' interruptor/caso' más rápido/más legible. Y 'profileType' realmente debería ser una enumeración, no una cadena arbitraria. Aparte de eso, es una gran respuesta. :) – Aaronaught

+3

Sí, no hay desacuerdo allí, pero acabo de ir con la API dada por el OP :) –

+0

¿De qué manera puede cambiar si no sé en tiempo de compilación el número de repositorios? Y si mi wcf solo tiene dependencias con la biblioteca de registro y estos repositorios, ¿cuál es la mejor opción de DI Container? ¿MEF es una buena choiche en este escenario? – tartafe

4

Gran respuesta por Mark, sin embargo la solución dada no es fábrica abstracta pero la aplicación de la norma Patrón de fábrica. Compruebe cómo las clases de Marks encajan en el diagrama UML de patrón de fábrica estándar. Click here to see above classes applied to Factory pattern UML

Dado que en el patrón de fábrica, la fábrica está al tanto de las clases concretas, podemos hacer que el código de ProfileRepositoryFactory sea mucho más simple, como se muestra a continuación. El problema de inyectar los diferentes repositorios a fábrica es que tiene más cambios de código cada vez que agrega un nuevo tipo de concreto. Con código de abajo es suficiente con actualizar el interruptor para incluir 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 patrón más avanzada que se utiliza para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas. El diagrama de clases UML disponible here lo explica bien.

Cuestiones relacionadas