2012-02-02 6 views
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」は型引数で使用することはできません。私はこれをしたい理由

理由は、私が&の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>(); } 
    } 
} 

は私の同期モデル&のViewModelを持つためのより良い方法を提案する。ViewModelには、ビューのためのデータを提供するために存在

+0

恐らく、Automapperを代わりに使用してください。 – CodesInChaos

+0

私はすでにそれを使用していますが、チームメンバーは大きくてネストされたエンティティのためにそれを好きではありません – hungryMind

答えて

0

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

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

public class OtherType { } 
public class Address { } 

ような何かを試すことができます。そしてIPerson

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; } 
} 
+0

に変更しましたが、これでViewModelが確実になります – hungryMind

+0

これは機能しますか? C#では共変な戻り値の型は許可されません。 – Lukazoid

+0

@ルカゾイド、ええ、私は混乱してコードを修正しました。今それは動作します。 – oleksii

1

。これは、モッズなければならないことを意味しビューの要件を満たしています。通常、これらの要件はモデルの要件と同じではありません。つまり、通常、モデルとViewModelは同期していないため、モデルとは異なります。あなたのアプローチでは、ViewModelは値を追加せず、削除することができます。

ViewModelとモデルをマップするには、AutoMapperを使用できます。

1

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

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

は本当に一般的なクラスが必要ですか? ObservableCollection<T>List<T>は両方ともICollection<T>を実装しているため、インターフェイス内のアドレスとその他のタイプをそれぞれICollection<Address>ICollection<OtherType>と宣言できる場合があります。

(AddressViewは何ですか?)

+0

問題はクラスではなくインターフェイスで、私のインターフェイスがコンパイルされています。 AddressViewを – hungryMind

0

あなたの一般的な制約は、TがTのICollectionを実装する必要があります強制されますか?それは許されない無限に再帰的です。

ジェネリック型にもパラメータを指定することはできません。は許可されていません。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です。

+0

いいえ、これは単なる例です。私のエンティティには多くの種類のリストが含まれています。すべての型を指定するのは良い考えではありません – hungryMind

+0

あなたのインタフェースが単に 'ICollection'sを返すことができないのはなぜですか?あなたの実装は 'ICollection'を返しますか?そして、それぞれの実装は 'ICollection'の異なる実装を返すことができますか? – Lukazoid

+0

私は何を意味するのか@オレクシスの答えを見て、それは私が行くものです。 – Lukazoid

関連する問題