2013-02-07 46 views
0

我正在重新構建和構建Win8應用程序解決方案。我一直在將我的關鍵組件分離到他們自己的項目中。我有:界面上的循環依賴

  • 它採用MVVMLight(因此SimpleIOC)主Win8的項目
  • 包含所有我serialisable模型類
  • 各種類導航和系列化
  • 一個
  • 一個服務項目的樣板工程我的所有接口的合同項目
  • 包含主應用程序使用的視圖模型的View Models項目。

到目前爲止,我已經有了工作,但有一個案例我無法找出最佳結構。在我的ViewModels項目中,我有一個數據映射器類。基本上它需要一個模型,並吐出一個視圖模型。我一直試圖將它移動到服務層,併爲它創建一個接口,但是爲了瞭解ViewModel類而在接口中碰到一個依賴關係,所以現在基本上有一個循環依賴關係。

編輯:我應該解釋說,ViewModels本身需要利用這個映射器。例如,我有一個整體的PageViewModel,它包含了XAML頁面所需的所有內容。其中之一就是VehicleViewModel的清單,它是包含一些視圖特定屬性的車輛清單。因此,PageViewModel將調用數據服務,獲取Vehicle模型,然後使用映射器將其轉換爲VehicleViewModel。

這裏是接口。你可以看到,我想從兩個方法中返回一個ViewModel對象。然而,ViewModel項目已經有了對這個合同項目的引用,所以我目前不會構建。

我玩弄了爲viewmodels創建和創建接口的想法,但後來我有很多工作來創建接口,我不確定這是最好的方法。我忽略了這裏顯而易見的東西嗎?

編輯:這裏有一個實際執行現有的接口:

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

您可以用web界面上的mapperService構建一個對象,然後將該對象傳遞給您的服務層映射您需要的對象並以您想要的格式將其發送回Web層? – 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 
    } 
} 

很明顯,您需要在引用您的合同,模型和視圖模型項目的項目中實現此類。

+0

我從來沒有真正在一些地方使用基礎知識以外的泛型。我想我可以看到你的建議,只是我不知道如何實施它。我已經將實際代碼添加到了原始問題中,以顯示我在做什麼。每個映射器都有不同的邏輯。 – stevejgordon