2

LINQ-to-SQLで作成されたエンティティがいくつかあります。これらのエンティティのうち6つ(主にドロップダウンリストで値を表す)は、私が呼び出したインターフェイスを実装していますIValue。これを行ったのは、UIレイヤーがいくつかの特殊なケース、特に、レコードの元の値に削除済みのフラグが設定されている場合に何を表示するかを考慮する必要があるためです。

リポジトリには、ListAllXXXこれらの人のためのさまざまな方法があります。これらはすべて、適切なエンティティタイプに入力されたジェネリックリストを返します。例:

public static List<ContactType> ListAllContactTypes(DeletedOptions getDeleted)
{ /* requisite code */ }

ContactTypeIValueもちろん、実装します。

UI固有のリストを実際に取得するように設計された別のサービスセットがあります。したがって、基本的なパターンは次のとおりです。

// One of these for each entity type
public static List<IValue> GetContactTypeList(ContactType target)
{
    List<IValue> ret = LovRepository.ListAllContactTypes(DeletedOptions.NoDeleted);
    PrepList(ret, target);

    return ret;
}

// All of the above methods use this guy
private static void PrepList(List<IValue> list, IValue targetEntity)
{
    list.Insert(0, new DummyValue() { Description = "Add New ... ", ID = 0 });

    if (targetEntity != null && !(list.Contains(targetEntity))
        list.Add(new DummyValue() { Description = "[deleted]", ID = -1 });
}

DummyValue(これは私が作成した単純なクラスであり、も実装していることに注意してください。このクラスIValueの全体的な目的は、「新規追加」および「削除」メニューオプションとして機能することです。)

これはすべて、ほぼ同一のコードを数十行書きたくなかったために発生しました。これは、共分散があると思った理由です。

ここに書かれているコードはコンパイルされません。私はラインList<IValue>上で手動キャストを試しました。ListAllContactTypesこれはコンパイルされますが、実行時に無効なキャスト例外で失敗します。

ここに行きたい場所に行くにはどうすればよいですか?インターフェイスで一般的な差異を使用することに制限はありますか?もしそうなら、それを回避する簡単な方法はありますか?そうでない場合、私は非常に反復的であるがわずかに異なるコードの束を書くことに追いやられていますか?(私が本当に避けようとしていることです。)

これは重複している可能性がありますが、私のGoogle-fuは現在私を失敗させています。もしそうなら、それに応じて閉じるために投票してください。(もしそうなら、私は投票を重ねます!)

4

1 に答える 1

1

共変性と反変性はデリゲート宣言とインターフェイス宣言でのみ使用できるため、コードは機能しません。ただし、Cast拡張メソッドを使用して結果をキャストし、コードを機能させることができます。

List<IValue> ret = LovRepository.ListAllContactTypes(DeletedOptions.NoDeleted)
    .Cast<IValue>().ToList();

これにより、リスト内の各要素がキャストされ、IValue要素の新しいリストが作成されます。

これが必要な理由は、型の安全性と関係があります。もちろん、サンプルコードでは問題ありません。ただし、メソッドListAllContactTypesは、タイプList<ContactType>を返すように宣言されています。それをList<IValue>に割り当てることができれば、任意のIValueを入れることができます-したがって、他のコードがリストにContactTypeを明示的に含むことを期待している場合、そのコードは壊れます。この例を考えてみましょう。

List<ContactType> listOfContactType =  // Some method ....
List<IValue> list = listOfContactType; // This line not allowed.

それをコンパイルすると、次のことができるようになります。

list.Insert(0,new DummyType());

ただし、元の参照を考慮する必要があります。元の参照では、次のことが許可されます。

ContactType contact = listOfContactType[0];  // Woops, element is not ContactType.

リスト内の要素がDummyTypeであるため、これを行うことはできません。ありがたいことに、コンパイラは私たちを早く救ってくれました。

于 2010-04-27T20:15:54.143 に答える