2008-09-10 1 views
0

私が使用している重要な内部テストツールで使用されているファイルのエディタに取り組んでいます。ツールそのものは大規模で複雑で、リファクタリングや書き換えは将来のために費やせるリソースよりも多くのリソースを必要とするため、大きな変更になると私の手は縛られます。私は.NET言語を使用する必要があります。いくつかの無関係な型を格納する必要があるが、特定の型を要求に応じて提供する必要がある場合はどうすればよいですか?

これらのファイルは、ツールで使用される4つのクラス(A、B、C、Dと呼ぶ)のXMLシリアル化バージョンです。すべてがうまくいくと、クラスはツリー構造を形成します。私たちのエディタは、一連のファイルを読み込んでデシリアライズし、それらの関係を整理し、見つかった悪い状態を追跡することによって動作します。このアイデアは、私たちがこれらのファイルを手で編集することから遠ざかり、多大なエラーを招いています。

特定のタイプのエラーについては、問題のあるすべてのファイルのコレクションを維持したいと考えています。 4つのクラスすべてに問題がある可能性があります。できるだけコードの重複を減らしたいと思います。重要な要件は、ユーザーがセット内のアイテムを取得できる必要があることです。たとえば、すべてのAオブジェクトをエラーで取得し、コレクション全体を反復処理して、GetAs()メソッドと比較して、必要なものを選択できないようにする必要があります。だから、私の最初の考えは非直列化されたオブジェクトと、エラーを示すために、いくつかのメタデータに関連する一般的な項目にすることでした。そして、

public class ErrorItem<T> 
{ 
    public T Item { get; set; } 
    public Metadata Metadata { get; set; } 
} 

を、私は、エラー項目のすべてを保持することができ、コレクションクラスを持っていると思いますユーザーが必要とするときに特定のクラスの項目を抽出するヘルパーメソッド。これが問題の始まりです。

いずれのクラスも共通の祖先(Object以外)を継承しません。これはおそらく最初のデザインの間違いでしたが、数日を費やして考えましたが、クラスは実際に各アイテムを一意に識別するGUIDプロパティ以外の共通点を持たないため、オリジナルのデザイナ相続によってそれらを関連付けることはなかった。つまり、統一されたエラーコレクションは、何が入ってくるのかを制限する基本クラスやインタフェースがないため、ErrorItem<Object>オブジェクトを格納する必要があります。

Public Class ErrorCollection 
{ 
    public ErrorItem<Object> AllItems { get; set; } 
} 

しかし、これはパブリックインターフェイスに影響します。私が本当に欲しいのは、このような適切なErrorItemジェネリック型を返すことです:

public ErrorItem<A>[] GetA() 

私だけErrorItem<Object>を保存することができますので、これは不可能です!私は頭の中でいくつかの回避策を実行しました。ほとんどの場合、それは適切なタイプの新しいErrorItemをオンザフライで作成することを含みますが、ちょっと醜い感じです。別の考え方では、アイテムをタイプ別に整理するためにDictionaryを使用していましたが、それでも正しいとは思われません。

ここで私を助けてくれるパターンがありますか?これを解決する最も簡単な方法は、A、B、C、およびDが派生する基本クラスを追加することですが、できるだけ元のツールに小さな影響を与えようとしています。初期のツールを変更するために必要な回避策のコストは十分ですか?

答えて

0

A、B、C、Dに共通点がない場合、基本クラスを追加しても実際には何も得られません。実際には空のクラスになり、実際にはオブジェクトと同じになります。

私は、ジェネリックスを持たないErrorItemクラスを作成し、Itemオブジェクトを作成し、参照されたオブジェクトを使用するときにいくつかのキャストを行います。Guid以外のA、B、C、Dクラスのいずれかのプロパティまたはメソッドを使用する場合は、とにかくキャストしなければなりません。

1

これはあなたが探しているものですか?あなたがItemsOfAをキャッシュしたい場合は

private List<ErrorItem<object>> _allObjects = new List<ErrorItem<object>>(); 

public IEnumerable<ErrorItem<A>> ItemsOfA 
{ 
    get 
    { 
     foreach (ErrorItem<object> obj in _allObjects) 
     { 
      if (obj.Item is A) 
       yield return new ErrorItem<A>((A)obj.Item, obj.MetaData); 
     } 
    } 
} 

あなたは簡単にそれを行うことができます。

private List<ErrorItem<A>> _itemsOfA = null; 

public IEnumerable<ErrorItem<A>> ItemsOfACached 
{ 
    if (_itemsOfA == null) 
     _itemsOfA = new List<ErrorItem<A>>(ItemsOfA); 
    return _itemsOfA; 
} 
1

私がこれまで一緒に行くよ答えはfryguybobとMendelt Siebengaからの回答の組み合わせです。

Mendelt Siebengaが指摘したように、基本クラスを追加するだけで名前空間が汚染され、同様の問題が発生します。私は何のアイテムがコレクションに入ることができるかについてより多くのコントロールを得るだろうが、私はまだErrorItem<BaseClass>を保存する必要があり、いくつかのキャストを行うので、私は同じ根本的な原因でわずかに異なる問題があるだろう。だからこそ私は答えとしてポストを選んだのです。何があってもキャストを行う必要があると指摘し、KISSは余分な基底クラスとジェネリックスがあまりにも多いと指示します。

私はfryguybobの答えがソリューション自体ではなく、キャッシュされていないバージョンを書くのを容易にするyield returnについて私に思い出させるのが好きです(私はLINQを使うつもりでした)。私はキャッシュされたバージョンは少し賢明ですが、予想されるパフォーマンスパラメータではキャッシュされていないバージョンは目立って遅くなりません。

+0

返信いただきありがとうございます。ほとんどの人は火事と忘れの質問をします。あなたの答えを見直し、あなたの結論を共有することで、価値を付け加えることができました。 – Mendelt

関連する問題