0

Win8 アプリ ソリューションのリファクタリングと構造化を行っています。私は主要なコンポーネントを独自のプロジェクトに分けてきました。私は持っている:

  • MVVMLight (したがって SimpleIOC) を使用するメインの Win8 プロジェクト
  • すべてのシリアル化可能なモデル クラスを含むモデル プロジェクト
  • ナビゲーションとシリアル化のためのさまざまなクラスを持つサービス プロジェクト
  • すべてのインターフェイスのコントラクト プロジェクト
  • メイン アプリで使用されるビュー モデルを含むビュー モデル プロジェクト。

これまでのところ、うまく機能していますが、最適な構造を見つけられないケースが 1 つあります。私の ViewModels プロジェクト内には、データ マッパー クラスがあります。基本的に、モデルを取り込み、ビュー モデルを吐き出します。これをサービスレイヤーに移動しようとして、そのためのインターフェイスを作成しましたが、ViewModel クラスの知識のためにインターフェイス内で依存関係に遭遇したため、現時点では基本的に循環依存関係があります。

編集: ViewModels 自体がこのマッパーを利用する必要があることを説明する必要があります。たとえば、XAML ページに必要なすべてを保持する全体的な PageViewModel があります。これらの 1 つは、いくつかのビュー固有のプロパティを含む車両のリストである VehicleViewModels のリストです。したがって、PageViewModel はデータ サービスを呼び出し、Vehicle モデルを取得し、マッパーを使用してこれを VehicleViewModel に変換します。

これがインターフェースです。

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

ご覧のとおり、2 つのメソッドから 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);
    }
}

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

明らかに、コントラクト、モデル、およびビューモデル プロジェクトを参照するプロジェクトにこのクラスを実装する必要があります。

于 2013-02-07T19:43:31.703 に答える
0

質問を正しく理解している場合は、1 つのオブジェクトからビュー モデルにマップしようとしています。この場合、独自のマッパー ツールを作成することは、使用法にとって非常に効率的ではない可能性があります。Automapperを確認してください。Mapper.Map() メソッドを呼び出すことで、あるオブジェクトを別の型にマップできます。

あなたが実際に達成したいことを考えすぎているように私には見えます。VehicleViewModel が必要な場合は、車両を VehicleViewModel にマップし、マッピング メソッドを呼び出します。Automapper を使用すると、これを非常に簡単に行うことができます。しかし、一般的には、ビューモデルにアクセスできるレイヤーに存在する仲介マッパーが必要であり、さまざまなタイプのマッピングを行います。

于 2013-02-07T19:33:09.790 に答える