2013-02-07 3 views
0

Win8 App Solution을 다시 고려하고 구조화하는 중입니다. 내 주요 구성 요소를 자신의 프로젝트로 분리 해왔다. 내가 가진 :인터페이스상의 순환 종속성

  • MVVMLight (따라서 SimpleIOC)를 사용하여 주요 Win8 프로젝트
  • 내 모든 serialisable 모델 클래스를 탐색 및 직렬화
  • A에 대한 다양한 클래스와
  • 서비스 프로젝트를 포함
  • 모델 프로젝트 내 모든 인터페이스에 대한 계약 프로젝트
  • 주 앱에서 사용하는보기 모델이 포함 된 모델보기 프로젝트입니다.

지금까지 나는 일을하고 있지만 최선의 구조를 해결할 수없는 경우가 하나 있습니다. ViewModels 프로젝트 내에서 데이터 매퍼 클래스가 있습니다. 기본적으로 모델을 가져 와서 뷰 모델을 뱉어냅니다. 나는 이것을 서비스 레이어로 옮기려고 노력해 왔고 인터페이스를 만들었지 만 인터페이스 내에서 ViewModel 클래스에 대한 지식을 얻기 위해 의존성에 부딪혔다. 그래서 본질적으로 원형 의존성을 가지고있다.

편집 : ViewModels 자체가이 매퍼를 사용해야한다고 설명해야합니다. 예를 들어 XAML 페이지에 필요한 모든 것을 포함하는 전체 PageViewModel이 있습니다. 이 중 하나는 VehicleViewModels의 목록입니다. VehicleViewModels는 특정보기 속성을 포함하는 차량 목록입니다. 따라서 PageViewModel은 데이터 서비스를 호출하고 Vehicle 모델을 가져온 다음 매퍼를 사용하여이를 VehicleViewModel로 바꿉니다.

다음은 인터페이스입니다.

namespace MyApp.Contracts 
{ 
    public interface IDataMapperService 
    { 
     VehicleViewModel VehicleToVehicleViewModel(Vehicle v); 
     TripViewModel TripToTripViewModel(Trip t); 
    } 
} 

두 가지 방법으로 ViewModel 개체를 반환하고 싶습니다. 그러나 ViewModel 프로젝트에는 이미이 Contracts 프로젝트에 대한 참조가 있으므로이 프로젝트는 현재 빌드되지 않습니다.

나는 뷰 모델을 만들기위한 인터페이스를 가지고 놀랐지 만, 인터페이스를 만드는 데 많은 노력을 기울이고 있으며, 이것이 최선의 방법이라고 확신하지 못합니다. 나는 여기서 명백한 것을 간과 했는가?

편집 : 여기에 현재 인터페이스의 실제 구현의 :

public VehicleViewModel VehicleToVehicleViewModel(Vehicle v) 
    { 
     var newVehicle = new VehicleViewModel(v.VehicleID, v.Make, v.Model, v.Petrol, v.Registration); 

     foreach (Trip t in v.Trips) 
     { 
      newVehicle.Trips.Add(TripToTripViewModel(t)); 
     } 

     IQueryable<Trip> trips = v.Trips.AsQueryable(); 

     var now = DateTime.Now.Date; 

     var firstofmonth = new DateTime(now.Year, now.Month, 1); 

     while (now.DayOfWeek != DayOfWeek.Monday) now = now.AddDays(-1); 

     var weektrips = from t in trips 
         where t.Date >= now 
         select t; 

     var monthtrips = from t in trips 
         where t.Date >= firstofmonth 
         select t; 

     newVehicle.TripsThisWeek = weektrips.Count(); 
     newVehicle.MilesThisWeek = (int)Math.Round(weektrips.Sum(t => t.Mileage), 0); 
     newVehicle.TripsThisMonth = monthtrips.Count(); 
     newVehicle.MilesThisMonth = (int)Math.Round(monthtrips.Sum(t => t.Mileage), 0); 

     return newVehicle; 
    } 

    public TripViewModel TripToTripViewModel(Trip t) 
    { 
     var newTrip = new TripViewModel(t.TripID, t.Date, t.Mileage); 
     return newTrip; 
    } 

답변

0

난 당신이 하나의 개체에서보기 모델에 매핑하려고 정확하게 질문을 이해하고합니다. 이 경우 자신의 매퍼 도구를 쓰는 것이 사용상의 효과가 없을 수도 있습니다. 체크 아웃 Automapper Mapper.Map() 메서드를 호출하여 한 객체를 다른 유형에 매핑 할 수 있습니다.

당신이 실제로 달성하기를 원하는 것을 생각하고있는 것처럼 보입니다. VehicleViewModel이 필요한 경우 VehicleViewModel에 차량을 매핑하고 매핑 방법을 호출하십시오. Automapper는이 작업을 매우 쉽게합니다. 그러나 일반적으로보기 레이어에 액세스 할 수있는 위치에 머무르는 중개자가 필요하며 여러 유형의 매핑이 필요합니다.

+0

답장을 보내 주셔서 감사합니다. automapper를 보았지만 현재 WinRT를 지원하지 않습니다. 또한 맵핑 프로세스 중에 계산 된 일부 필드가 추가되어 직접 매핑이 아닙니다 (예 : 일부 복잡한 총계). 현재 내 PageViewModels는 MapperService를 호출해야하지만 동시에 MapperService는 VehicleViewModel 클래스를 출력해야합니다. PageViewModels와 ObjectViewModels에 대해 다른 레이어를 추가했는지 궁금합니다. – stevejgordon

+0

웹 레이어의 mapperService에 필요한 데이터로 객체를 구성한 다음 해당 객체를 서비스 레이어에 전달하여 필요한 객체를 매핑하고 원하는 형식으로 웹 레이어로 다시 보낼 수 있습니까? – Robert

1

제네릭을 사용하여 맵퍼 인터페이스를 만들 수 있습니다.

namespace MyApp.Contracts 
{ 
    public interface IDataMapperService<ViewModelT, ModelT> 
    { 
     ViewModelT ModelToViewModel(ModelT v); 
    } 
} 

서비스는 다음 IDataMapperService<VehicleViewModel, Vehicle>IDataMapperService<TripViewModel, Trip>를 반환 할 수 있습니다. 보기 모델 및 모델이 일반 제약 조건과 함께 사용하기위한 간단한 인터페이스를 만들 수 있습니다.

namespace MyApp.Contracts 
{ 
    public interface IModel {} 
    public interface IViewModel {} 

    public interface IDataMapperService<ViewModelT, ModelT> 
     where ViewModelT : IViewModel 
     where ModelT : IModel 
    { 
     ViewModelT ModelToViewModel(ModelT v); 
    } 
} 

그런 다음 새 인터페이스를 구현하려면 매퍼 클래스를 만들어야합니다.

public class DataMapperService : IDataMapperService<VehicleViewModel, Vehicle> 
{ 
    public VehicleViewModel ModelToViewModel(Vehicle v) 
    { 
     //implementation goes here 
    } 
} 

물론, 당신은 당신의 계약, 모델, viewmodels 프로젝트를 참조하는 프로젝트에서이 클래스를 구현해야합니다.

+0

저는 일부 장소에서 기본을 뛰어 넘는 제네릭을 실제로 사용한 적이 없습니다. 네가 제안하고있는 것을 볼 수있을 것 같아, 단지 그것을 구현하는 방법을 모르겠다. 나는 원래의 질문에 실제 코드를 추가하여 내가하는 일을 보여 주었다. 각 매퍼에는 별개의 논리가 있습니다. – stevejgordon