2011-01-24 17 views
6

Używam ValueInjecter do mapowania właściwości z modelu Domeny do DTO serwowanego za pośrednictwem Warstwy usługi. Usługa, o której mowa, akceptuje również aktualizacje ... tak, że zaktualizowany DTO jest przekazywany, a następnie jest on wstrzykiwany do obiektu domeny i zapisywany.Wartość Injecter: Dto do Modelu Domeny (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; 
    } 

Teraz wszystko to powyższy kod robi to aktualizuje Member.Country.Code nieruchomości, która nie jest oczywiście to, co muszę zrobić.

Więc z docs, pomyślałem, że muszę stworzyć nadpisanie i dostał to:

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; 
    } 

Mój problem jest podczas debugowania, CountryLookup nigdy nie jest wywoływana.

Możliwe przyczyny mogę myśleć:

  • klas Nhibernate Proxy powodując wartość injecter nie pasuje typ kraju? To nie ma sensu, ponieważ działa podczas spłaszczania.
  • Być może niezwiązanie z jakiegoś powodu nie zwalnia. Tj Dto jest CountryCode i domeny jest Country.Code

muszę użyć właściwości CountryCode na Dto wywołać countryService.LookupCode powrót poprawny obiekt używać podczas iniekcji aktualizacji.

+0

powiedz nam, co próbujesz osiągnąć, pierwsza próba działa, ale nie jest to, czego potrzebujesz, czego potrzebujesz? – Omu

+0

Twoja iniekcja o nazwie CountryLookup zostanie rozwinięta z ciągu znaków do kraju, co oznacza, że ​​chce uzyskać wartość z kodu krajowego typu i umieścić go w kodzie kraju o typie kraju – Omu

+0

@Omu jest to poprawne, na przykład, jeśli mój obiekt Country to Kraj: {kod : USA, Name: United States} i moje DTO przechodzi w CountryCode: "CA" po prostu ustawia właściwość Country.Code na CA i pozostawia właściwość 'Name' jako Stany Zjednoczone. Pamiętaj, że aktualizuję wstępnie wypełniony obiekt domeny ... Z tego powodu muszę wywołać mój countryService w celu wyszukania poprawnego obiektu Country. Chcę przechwycić "Kod" z DTO, a następnie użyć tego kodu do wyszukania właściwego obiektu Country. – Galen

Odpowiedz

3

Korzystanie sugestia/odwołanie od Omu To był specyficzny kod do problemu.

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

tak, to powinno działać (chociaż nie widzę gdzie ustawiłeś parametr konstruktora ICountryService), chciałem tylko, abyś spojrzał na bardziej ogólny sposób, zastrzyk na wszystko – Omu

+0

Parametr konstruktora ustawiany jest w tym przypadku przez Castle Windsor iniekcja zależności. Jest to trochę niemy do rozwiązania, ponieważ faktyczne wywołanie usługi nie jest tak istotne. – Galen

+0

Ponadto, rozważę ogólne rozwiązanie tego projektu, korzystając z Waszych sugestii, dziękuję :) – Galen

0

Czy struktura wywołuje metodę setera? W większości frameworków DI standard to małe litery w metodzie setMethod(). Tylko zalecenie na samą myśl.

+0

Czy odwołujesz się do metody SetValue? Jeśli tak, jest to część struktury ValueInjecter. – Galen

+0

Nick, to jest .NET, nie Java. Standard .NET jest typem pascala dla nazw metod, a nie przypadku wielbłądów. – Phill

3

unflattening byłoby to zrobić:

entity.Country.Code <- dto.CountryCode 

czego potrzebujesz to:

entity.Country <- dto.CountryCode 

więc rozwiązaniem dla Ciebie byłoby, aby odziedziczyć ExactValueInjection gdzie byś poszedł z CountryCode krajach.

co polecam Ci zrobić jest zrobić to samo, że zrobiłem na żywo demo inny projekt kopalni http://awesome.codeplex.com

gdzie mam coś takiego:

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;} 
    } 

i korzystać z tych zastrzyki, aby przejść z jednostki do dto iz powrotem

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; 
      } 
     } 

te zastrzyki będą obsługiwać nie tylko iść z int? do Kraj iz powrotem, ale także innego rodzaju, która dziedziczy Podmiot

+0

Ten komentarz prowadzi do konkretnej odpowiedzi na mój problem, ale nie pokazuje dokładnej odpowiedzi, która źle post. Czy to może być + 1-kowe jako pomocne. – Galen