2011-01-24 18 views
6

Estoy usando ValueInjecter para mapear propiedades desde un modelo de Dominio hasta una DTO servida a través de una Capa de Servicio. El servicio en cuestión también acepta actualizaciones ... por lo que se transfiere una DTO actualizada que luego se inyecta al objeto de dominio y se guarda.Inyector de valor: Dto al modelo de dominio (NHibernate)

// Domain 
    public class Member 
    { 
     public Country Country { get; set; } 
    } 

    public class Country 
    { 
     public string Code { get; set; } 
     public string Name { get; set; } 
    } 

    //Dto 
    public class MemberDto 
    { 
     public string CountryCode { get; set; } 
    } 

    //Transformation Method attempt 1 
    public Member InjectFromDto (MemberDto dto, Member source) 
    { 
     source = source.InjectFrom<UnflatLoopValueInjection>(dto); 
     return source; 
    } 

Todo esto hace es el código de seguridad actualiza la propiedad Member.Country.Code lo que obviamente no es lo que necesito hacer.

Así que a partir de los documentos, que pensé que necesitaba para crear una anulación y tiene esto:

public class CountryLookup: UnflatLoopValueInjection<string, Country> 
    { 
     protected override Country SetValue(string sourcePropertyValue) 
     { 
      return countryService.LookupCode(sourcePropertyValue); 
     } 
    } 


//revised transformation call 
//Transformation Method attempt 2 
    public Member InjectFromDto (MemberDto dto, Member source) 
    { 
     source = source.InjectFrom<UnflatLoopValueInjection>(dto) 
         .InjectFrom<CountryLookup>(dto); 
     return source; 
    } 

Mi problema es durante la depuración, CountryLookup nunca se llama.

Las posibles razones que se me ocurren:

  • clases Nhibernate proxy causando valor injecter que no coincide con el tipo de país? Aunque esto no tiene sentido porque funciona durante el aplanamiento.
  • Quizás el unflattening no se dispare por alguna razón. Es decir Dto es countryCode y Dominio es COUNTRY.CODE

necesito utilizar la propiedad countryCode en el Dto para llamar a un countryService.LookupCode para devolver el objeto correcto a utilizar durante la inyección de actualización.

+0

dinos qué intentas lograr, el primer intento funciona, pero no es lo que necesitas, ¿qué necesitas? – Omu

+0

su inyección llamada CountryLookup desentrelazará de cadena a País, lo que significa que busca obtener el valor de CountryCode de tipo cadena y ponerlo en País.Código del tipo País – Omu

+0

@Omu eso es correcto así que por ejemplo si mi País es País: {Código : USA, Nombre: Estados Unidos} y mi Dto pasa en CountryCode: "CA" simplemente establece la propiedad Country.Code en CA y deja la propiedad 'Name' como Estados Unidos. Recuerde que estoy actualizando un objeto de dominio rellenado previamente ... Debido a esto, debo llamar a mi paísServicio para buscar el objeto Country correcto. Quiero capturar el 'Código' del Dto y luego usar ese código para buscar el objeto Country correcto. – Galen

Respuesta

3

El uso de la sugerencia/referencia de Omu este era el código específico para el problema.

public class CountryLookup : ExactValueInjection 
    { 
     private ICountryService countryservice; 

     public CountryLookup(ICountryService countryService) 
     { 
      this.countryService = countryService; 
     } 

     protected override bool TypesMatch(Type s, Type t) 
     { 
      return (s == typeof(string)) && (t == typeof (Country)); 

     } 
     protected override Object SetValue(object v) 
     { 
      if (v == null) 
       return null; 

      var country = countryService.LookupCode((string) v); 
      return country; 
     } 

     public override string SourceName() 
     { 
      return "CountryCode"; 
     } 

     public override string TargetName() 
     { 
      return "Country"; 
     }  
    } 

public Member InjectFromDto (MemberDto dto, Member source) 
{ 
    source = source.InjectFrom<UnflatLoopValueInjection>(dto) 
        .InjectFrom<CountryLookup>(dto); 
    return source; 
} 
+1

sí, esto debería funcionar (aunque no veo dónde se establece el parámetro de constructor ICountryService), solo quería que miraras de una manera más genérica, una inyección para todo – Omu

+0

El parámetro constructor se establece en este caso a través de Castle Windsor inyección de dependencia. Es un poco mudo para la solución, ya que la llamada al servicio de búsqueda real no es relevante. – Galen

+0

Además, consideraré una solución genérica para este proyecto usando sus sugerencias, gracias :) – Galen

0

¿Es un marco que llama al método setter? En la mayoría de los marcos DI, el estándar es 's' en minúsculas en setMethod(). Solo una primera recomendación de pensamiento.

+0

¿Te refieres al método SetValue? Si es así, eso es parte del marco ValueInjecter. – Galen

+0

Nick, esto es .NET, no Java, el estándar .NET es un caso Pascal para nombres de métodos, no para camel. – Phill

3

unflattening sería hacer esto:

entity.Country.Code <- dto.CountryCode 

lo que necesita es:

entity.Country <- dto.CountryCode 

lo que la solución para usted sería para heredar un ExactValueInjection donde va a ir de countryCode al País.

lo recomiendo que hagas es hacer lo mismo que hice en la demostración en vivo de otro proyecto mío http://awesome.codeplex.com

donde tengo algo como esto:

public class Entity 
    { 
     public int Id{get;set;} 
    } 
    public class Member : Entity 
    { 
     public Country Country{get;set;} 
    } 
    public class MemberDto : DtoWithId 
    { 
     public int? Country {get;set;} 
    } 

y el uso de estos inyecciones para ir de entidad a dto y volver

public class NullIntToEntity : LoopValueInjection 
     { 
      protected override bool TypesMatch(Type sourceType, Type targetType) 
      { 
       return sourceType == typeof(int?) && targetType.IsSubclassOf(typeof(Entity)); 
      } 

      protected override object SetValue(object sourcePropertyValue) 
      { 
       if (sourcePropertyValue == null) return null; 
       var id = ((int?) sourcePropertyValue).Value; 

       dynamic repo = IoC.Resolve(typeof(IRepo<>).MakeGenericType(TargetPropType)); 

       return repo.Get(id); 
      } 
     } 
//(you also need to have a generic repository, notice IRepo<>)  
    public class EntityToNullInt : LoopValueInjection 
     { 
      protected override bool TypesMatch(Type sourceType, Type targetType) 
      { 
       return sourceType.IsSubclassOf(typeof (Entity)) && targetType == typeof (int?); 
      } 

      protected override object SetValue(object o) 
      { 
       if (o == null) return null; 
       return (o as Entity).Id; 
      } 
     } 

estas inyecciones se manejarán no solo yendo de int? a País y la espalda, sino también cualquier otro tipo que hereda Entidad

+0

Este comentario condujo a la respuesta específica a mi problema pero no muestra la respuesta exacta, lo cual está mal publicado. ¿Puede esto ser +1 como útil? – Galen

Cuestiones relacionadas