0

我正在重构和构建 Win8 应用解决方案。我一直在将我的关键组件分离到他们自己的项目中。我有:

  • 使用 MVVMLight(以及 SimpleIOC)的主要 Win8 项目
  • 一个包含我所有可序列化模型类的模型项目
  • 具有用于导航和序列化的各种类的服务项目
  • 我所有接口的合同项目
  • 包含主应用程序使用的视图模型的视图模型项目。

到目前为止,我已经完成了一些工作,但是有一个案例我无法制定出最佳结构。在我的 ViewModels 项目中,我有一个数据映射器类。基本上它接受一个模型并吐出一个视图模型。我一直在尝试将其移至服务层并为其创建一个接口,但在接口中遇到了一个依赖关系以了解 ViewModel 类,因此目前基本上具有循环依赖关系。

编辑:我应该解释一下 ViewModels 本身需要使用这个映射器。例如,我有一个包含 XAML 页面所需的所有内容的整体 PageViewModel。其中之一是 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;
    }
4

2 回答 2

1

您可以使用泛型来创建映射器接口。

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

然后,您的服务可以返回 anIDataMapperService<VehicleViewModel, Vehicle>和 an 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
    }
}

显然,您需要在引用您的协定、模型和视图模型项目的项目中实现此类。

于 2013-02-07T19:43:31.703 回答
0

如果我正确理解了这个问题,那么您正在尝试从一个对象映射到一个视图模型。如果是这种情况,编写自己的映射器工具对您的使用可能不是超级有效。查看Automapper它将允许您通过调用 Mapper.Map() 方法将一个对象映射到另一种类型。

在我看来,您似乎在思考您真正想要完成的事情。如果您需要 VehicleViewModel,则将车辆映射到 VehicleViewModel 并调用您的映射方法。Automapper 让这一切变得超级简单。但一般来说,您只需要一个中间映射器,它位于可以访问您的视图模型的任何层上,并为不同类型进行映射。

于 2013-02-07T19:33:09.790 回答