1

次のように、類似したエンティティが異なるタイプのコレクションを持つ2つの場所にあるアプリを設計しています。

モデル:

class PersonModel {
  public string Name { get;set;}
  public List<Address> Addresses { get;}
  public List<OtherType> OtherTypes { get;}
}

同様のビューモデル:

class PersonViewModel {
   public string Name { get;set;}
   public ObservableCollection<Address> Addresses { get; }
   public ObservableCollection<OtherType> OtherTypes { get; }
}

両方のエンティティの一貫性を保つために、両方がすべてのプロパティを実装することを保証する汎用インターフェイスを使用することを考えたので、次のようなものを作成しました。

public interface IPerson<T> where T: ICollection<T> {
   string Name { get;set;}
   T<Address> Addresses { get;}
   T<OtherType> OtherTypes [ get; } 
}

とクラスは

class PersonModel<List> {}
class personViewModel<ObservableCollection> {}

しかし、コンパイラは私のインターフェースをコンパイルする準備ができていません。:(言う、型パラメータ「T」は型引数と一緒に使用することはできません。

これが必要な理由、/からmodel&viewModelへの型変換を最小限に抑えたいと思いました。

私のviewModelは次のようになります、

class PersonViewModel<T> : IPerson<T> {
   public PersonViewModel(IPerson model){
      this.Model = model;
   }
   internal PersonModel Entity {
      get; set;
   }
   public string Name { 
      get{ return model.Name;} 
      set {model.Name = value;}
   }
   public T<Address> Addresses {
      get { return model.Addresses.Cast<T>(); }
   }
}

ModelとViewModelを同期させるためのより良い方法を提案してください。

4

4 に答える 4

1

ViewModelは、ビューのデータを提供するために存在します。これは、ビューの要件に従ってモデル化する必要があることを意味します。通常、これらの要件はモデルの要件と同じではありません。つまり、通常、モデルとViewModelは同期せず、異なります。あなたのアプローチでは、ViewModelは値を追加しておらず、削除される可能性があります。

ViewModelとモデルの間でマッピングするには、AutoMapperを使用できます。

于 2012-02-02T09:38:56.873 に答える
1

実装は次のようになります。

class PersonModel : IPerson<List> {}
class PersonViewModel : IPerson<ObservableCollection> {}

本当にジェネリッククラスが必要ですか?ObservableCollection<T>両方ともList<T>実装されているため、インターフェイスでAddressesとOtherTypesをそれぞれとICollection<T>として宣言できる可能性があります。ICollection<Address>ICollection<OtherType>

(AddressViewとは何ですか?)

于 2012-02-02T09:41:16.683 に答える
0

そのようにジェネリックを使用することはできません。あなたはこのようなことを試すことができます

public interface IPerson
{
    string Name { get; set; }
    ICollection<Address> Addresses { get; }
    ICollection<OtherType> OtherTypes { get; }
}

public class OtherType { }
public class Address { }

その後

class PersonModel : IPerson
{
    public PersonModel()
    {
        Addresses = new List<Address>();
        OtherTypes = new List<OtherType>();
    }

    public string Name { get; set; }
    public ICollection<Address> Addresses { get; private set; }
    public ICollection<OtherType> OtherTypes { get; private set; }
}

class PersonViewModel : IPerson
{
    public PersonViewModel()
    {
        Addresses = new ObservableCollection<Address>();
        OtherTypes = new ObservableCollection<OtherType>();
    }

    public string Name { get; set; }
    public ICollection<Address> Addresses { get; private set; }
    public ICollection<OtherType> OtherTypes { get; private set; }
}
于 2012-02-02T09:47:12.673 に答える
0

あなたの一般的な制約IPersonは、TがTのを実装しなければならないことを強制していICollectionますか?それは無限に再帰的であり、許可されません。

また、ジェネリック型にジェネリックパラメータを指定することはできないためT<Address>、許可されていません。これは、ジェネリック型であるかどうかがわからないためTです。

インターフェイスを次のように変更できます。

public interface IPerson<TAddressCol, TOtherCol> 
   where TAddressCol: ICollection<Address>
   where TOtherCol : ICollection<OtherType> 
{
   string Name { get;set;}
   TAddressCol Addresses { get;}
   TAddressCol OtherTypes [ get; } 
}

次に、次のように使用します。

class PersonModel<List<Address>, List<OtherType>> {}
class personViewModel<ObservableCollection<Address>, ObservableCollection<OtherType>> {}

それがあなたが望むアプローチを得る唯一の本当の方法だと思います。ICollection<Address>しかし、私はあなたのインターフェースが単にとを返すことを提案しますICollection<OtherType>。モデル/ビューモデルは、インターフェイスを介してコレクションを公開する必要がありますが、それぞれとして、ListまたはObservableCollectionそれぞれのバッキング実装を使用することを妨げるものは何もありません。

于 2012-02-02T09:49:14.927 に答える