2012-10-10 4 views
1

ValueIjector (NuGet의 최신 버전)를 사용하여 내 뷰 모델에 EntityFramework Code First 개체의 데이터를 주입하려고합니다. 나는 이것의 반대도하고 싶을 것이다. 그러나 이것은 내가 시작하고있는 시도이다.엔티티를 뷰 모델에 매핑하기 위해 사용자 정의 값 삽입을 어떻게 만듭니 까? 시도 포함

나는 다양한 매핑을 연구했으며 그 중 많은 시도를 해왔다. 나는 내가 필요한 것을하는 사람을 찾지 못했고, 나의 필요는 오히려 기본적인 것이라고 생각합니다. (그래서이 질문들 중 몇 가지는 각각 다른 대답을 얻습니다.).

나는 이것에 관해 나의 실사를 정말로 시도했다. 내가 봤 거든 및 CodePlex trolled ProDinner 응용 프로그램을 다운로드 한 (그것을 실행하고 디버그에서 코드를 단계별로).

저는 injecton을 처리 할 자체 ValueInjection 클래스가있는 지점에 있습니다. 나는 코드와 객체를 꽤 친숙한 방식으로 붙이기 때문에 코드와 객체를 잡아서 실행할 수 있습니다. 기본 LoopValueInjection을 사용하는 솔루션이 있지만 기본 엔티티에서 매핑으로 이동 한 다음 엔티티에 매핑하는 수동 배관이 필요하기 때문에 마음에 들지 않습니다. ProDinner 예제는 필자가 선호하는 템플릿 방식이 더 많았지 만 필자의 요구에 맞출 수 없었습니다.

내 코드가 논리적으로 엉망이라고 생각하는 이유는 소스 속성 유형이 단순한 개체가 아니라면 재귀 적 주입을 강제로 수행하는 방법을 이해할 수 없다는 것입니다. 이 예제에서 Person.Address. * 속성은 이름으로 일치하고 PersonViewModel 클래스의 속성을 입력합니다. 그러나 인젝션은 Person의 속성을 반복하고 Person.Address 속성의 이름과 유형을 일치 시키려고합니다.

내가이 재귀를 수행 할 것인가 라인

 Object result = Activator.CreateInstance(c.SourceProp.Type) 
      .InjectFrom<CloneInjection>(c.SourceProp.Value); 

생각,하지만 난 그것을하지 생각하지 않습니다.

그럼 ... 아무에게도이 문제를 해결할 수있는 방법을 알려 줄 수 있습니까?

////// ENTITY MODELS 

public class Person 
{ 
    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public virtual Address Address { get; set; } 
} 

public class Address 
{ 
    public int Id { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string Zip { get; set; } 
} 

////// VIEW MODEL 

public class PersonViewModel 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public int PersonId { get; set; } 
    public int AddressId { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string Zip { get; set; } 
} 

////// CUSTOM INJECTOR 
public class EntityToViewModel : ConventionInjection 
{ 

    protected override bool Match(ConventionInfo c) 
    { 
     //ignore int = 0 and DateTime = to 1/01/0001 
     if (c.SourceProp.Type == typeof(DateTime) && (DateTime)c.SourceProp.Value == default(DateTime) || 
      (c.SourceProp.Type == typeof(int) && (int)c.SourceProp.Value == default(int))) 
      return false; 

     if (c.SourceProp.Name == c.TargetProp.Name && c.SourceProp.Value != null) 
      return true; 

     if (c.SourceProp.Type == typeof(int) && 
      c.TargetProp.Type == typeof(int)) 
     { 
      if("id".Equals(c.SourceProp.Name.ToLower()) &&     
       c.TargetProp.Name.ToLower().EndsWith("id") && 
       c.TargetProp.Name.StartsWith(c.Source.Type.Name)) 
      return true; 
     } 

     //Transition logic to SetValue for value types. This should 
     //allow Address values on Person to be set. 
     if (!c.SourceProp.Type.IsPrimitive || c.SourceProp.Type.Equals(typeof(string))) 
      return true; 

     return false; 

     //put id logic matching here 
     //return c.SourceProp.Name == c.TargetProp.Name && c.SourceProp.Value != null; 
    } 

    protected override object SetValue(ConventionInfo c) 
    { 
     //If type is primative or string return the value as is 
     if (c.SourceProp.Type.IsPrimitive || c.SourceProp.Type.Equals(typeof(string))) 
      return c.SourceProp.Value; 

     Object result = Activator.CreateInstance(c.SourceProp.Type) 
      .InjectFrom<CloneInjection>(c.SourceProp.Value); 

     //for simple object types create a new instace and apply the clone injection on it 
     return result; 
    } 
} 

////// Program.cs 
public class Program 
{ 

    public static void Main(string[] args) 
    { 
     Person defaultPerson = getDefaultPerson(); 
     //Throws an error. I'm not sure where in the pipeline this occurs, but 
     //it seems to happen somewhere other than the Match & SetValue method of 
     //my EntityToViewModel injection 
     PersonViewModel pvm = CreateFromEntity(defaultPerson);   

     //Works, but want it more generic & without having to 
     //include hardcoded prefix for every non-simple object on my EF Model 
     pvm = CreateFromEntityWorking(defaultPerson); 
     Console.ReadLine(); 
    } 

    private static PersonViewModel CreateFromEntity(Person person) 
    { 
     PersonViewModel pvm = new PersonViewModel(); 
     pvm.InjectFrom<EntityToViewModel>(person); 
     return pvm; 
    } 

    ///WORKING MAPPING BUT SEEMS TOO HARDCODED 
    private static PersonViewModel CreateFromEntityWorking(Person person) 
    { 
     PersonViewModel personvm = new PersonViewModel(); 

     //Fill out view model properties with the same name as those on Person 
     personvm.InjectFrom(new LoopValueInjection().TargetPrefix("Person"), person); 

     if (person != null && person.Address != null) 
     { 
      //Fill out view model properties for the Address 
      personvm.InjectFrom(new LoopValueInjection().TargetPrefix("Address"), person.Address); 
     } 

     return personvm; 
    }  

    public static Person getDefaultPerson() 
    { 
     Person p = new Person(); 
     Address a = new Address(); 
     p.Id = 1; 
     p.FirstName = "John"; 
     p.LastName = "McClain"; 
     a.City = "New York"; 
     a.State = "New York"; 
     a.Zip = "55555"; 
     a.Id = 2; 
     p.Address = a; 
     return p; 
    } 

} 

답변

2

마침내 필요한 예제를 발견했습니다. 슬프게도, 모든 나의 수색에도 불구하고 나는 단지 이것들에 단지 도착했다. 그것은 내 자신의 잘못이 아닙니다. 그러나, 나는 발을 얼마나 발로 찼는 지에 따라 발이 아프다.

타당한 URL이 :

문서 (RTFM) 내 문제에 http://valueinjecter.codeplex.com/documentation

편평 예 & 협약 http://valueinjecter.codeplex.com/wikipage?title=flattening&referringTitle=Documentation

Unflattening 예 & 협약 http://valueinjecter.codeplex.com/wikipage?title=unflattening&referringTitle=Documentation

해결 방법 :

보기 모델에서 사용해야하는 규칙은 엔터티에 존재하는 최상위 수준 속성 인 의 속성 이름 앞에 접두사가없는 것입니다. 따라서 FirstName, LastName 및 Id가 모두 Person 엔터티의 최상위 속성으로 존재하는 아래 클래스의 내보기 모델 클래스에는 접두사가 붙지 않습니다. Person.Address 속성의 City, State, Zip 및 Id에 접두사가 붙습니다.

이상하게도 필자는 자신의 주입을 구현하는 동안이 솔루션을 생각했습니다. Entity에서 ViewModel으로가는 작업이 하나 있는데 ... 다른 방법은 아닙니다. 이러한 세부 주어진 그래서

public class PersonViewModelPrefixed 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public int Id { get; set; } 
    public int AddressId { get; set; } 
    public string AddressCity { get; set; } 
    public string AddressState { get; set; } 
    public string AddressZip { get; set; } 
} 

public static void Main(string[] args) 
{ 
     Person defaultPerson = getDefaultPerson(); 
     PersonViewModelPrefixed defaultPrefixedVm = getDefaultPrefixedViewModel(); 

     //flatten - Entity to View Model 
     PersonViewModelPrefixed pvm = Flatten(defaultPerson); 

     //unflatten - View Model to Entity 
     Person person2 = Unflatten(defaultPrefixedVm); 
    Console.ReadLine(); 
}  

//unflatten - View Model to Entity 
private static Person Unflatten(PersonViewModelPrefixed personViewModel) 
{ 
    Person p = new Person(); 
    p.InjectFrom<UnflatLoopValueInjection>(personViewModel); 
    return p; 
} 

//flatten - Entity to View Model 
private static PersonViewModelPrefixed Flatten(Person person) 
{ 
    PersonViewModelPrefixed pvm = new PersonViewModelPrefixed(); 
    pvm.InjectFrom<FlatLoopValueInjection>(person); 
    return pvm; 
} 

은, 하나는 패턴 화 된 & 패턴 화 해제 방법이 더 일반적인 만드는 방법에 대한 몇 가지 제안 사항이 있습니까? 그게 내가 다음에 작업 할거야.