0

私は、「テーブル駆動型」プログラムをオブジェクト指向プログラムに変換する任務を負っています。以前は、メモリ内に大きなテーブルを作成し、行と列を追加および削除し、すべてを文字列に解析することですべてが行われていました。かなりひどいものでした。これらのテーブルは、すべてが格納される基礎となるデータベースの構造を直接反映しています。

この問題ではLayer、約 100 個のプロパティを持つEventオブジェクトがあり、さらに約 20 個のプロパティを持つオブジェクトがあります。Layer/Event次に、ペアごとに約 10 個の計算値のセットを取得します。これらは、他の各テーブルを指す外部キーを持つ 3 番目のテーブルとして格納されました。

このデータを格納し、辞書のように値にすばやくアクセスするための適切なオブジェクト指向クラスを作成したいと思います。

私が最初に考えたのは、結果を辞書に索引付けすることでしたが、その使用は直感的ではないと感じました。

struct EventLayerResult { Decimal sum = 0; Long events = 0; Decimal average; ...}
//Performing Calculations
Dictionary<Tuple<Event,Layer>, EventLayerResult> _EventLayerResults ...;
foreach(Event evt in _Events)
    foreach(Layer lyr in _Layers)
        EventLayerResult elr = newLayerLosses[Tuple.Create(evt, lyr)];
        elr.sum += currentValue;
        elr.events += 1;
        elr.average += elr.Sum/elr.Events;
        etc...
//Using results
EventLayerResult temp = _EventLayerResults.TryGetValue(Tuple.Create(evt, lyr))
someLoss = temp == null ? 0 : temp.expectedLoss;

値を作成するたびに Tuple.Create を呼び出したり、一時オブジェクトの新しいインスタンスを作成したりする必要があるという考えは好きではありません。さらに、テーブルとは異なり、UI でこのテーブルをバインドしたい場合は、Field="Layer"、Field="Event"、Field="Loss" などにバインドすることはできません。Key.LayerKey.Event、などを抽出する複雑なバインド式Value.Loss。そのため、このようなデータ構造は避けたいと考えています。

これをオブジェクトにラップして、イベント/レイヤーの組み合わせの各値を簡単に検索できるようにすることもできますが、次のように使用できるように、計算されたプロパティごとに「get」メソッドを作成する必要はないと思います。

thisSum = _EventLayerResults.getSum(evt, lyr);
thisEvent = _EventLayerResults.getExpectedLoss(evt, lyr);

また、そのような構造に含まれる結果の完全なリストにバインドすることは不可能だと思います。

私の最終的な考え (私が使用しなければならないソリューションに最も近いと思うもの) は、参照する必要があるすべてのフィールドを持つオブジェクト/構造体の単純なコレクションです。

class EventLayerResult { Event oevent; Layer layer; Decimal sum; Long events...}
ObservableCollection<EventLayerResult> _EventLayerResults = ....
_EventLayerResults.Add( new EventLayerResult(){ oevent = evt, layer = lyr } );

これは非常に簡単にバインドできますが、問題は、このコレクションに「インデックス」がないことです。コレクションを監視するカスタムラッパークラスのように、この余分な荷物をすべて追加し始めない限り、後で特定のイベント/レイヤーの結果を検索するために O(Nevts * Nlyrs) 時間を見ています イベントを追加し、コレクションアイテムをディクショナリにインデックス付けしますなど

2 つの外部キーによってインデックス付けされた単純なテーブルをオブジェクト モデルに変換するたびに、他の人がこのすべてを経験することは想像できません。この種のデータセットを簡単に操作できる、私が知らない標準的なアプローチまたはデータ構造はありますか?

4

1 に答える 1

0

私がこれまでに思いついた最善の解決策は、OPで提案したように、コレクションをラップし、辞書を使用して外部キーのインデックスを作成することです。しかし、多くの作業のように思えます:

public class EventGroupIDLayerTuple : Tuple<Int32, Layer>
{
    public EventGroupIDLayerTuple(Int32 EventGroupID, Layer Layer) : base(EventGroupID, Layer) { }
    public Int32 EventGroupID { get { return this.Item1; } }
    public Layer Layer { get { return this.Item2; } }
}
public class EventGroupLayerResult
{
    public Int32 EventGroupID { get; set; }
    public Layer Layer { get; set; }
    //Computed Values
    public Decimal Sum { get; set; }
    public Decimal Average { get; set; }
    //...
}

/// <summary>ObservableCollection of computed EventGroup/Layer results that are also indexed
/// in a dictionary for rapid retrieval.</summary>
public class EventGroupLayerResultCollection : ObservableCollection<EventGroupLayerResult>
{
    Dictionary<EventGroupIDLayerTuple, EventGroupLayerResult> _Index = 
        new Dictionary<EventGroupIDLayerTuple,EventGroupLayerResult>();

    public EventGroupLayerResultCollection() : base() { }

    /// <summary>Will return the result for the specified eventGroupID/Layer
    /// combination, or create a new result and return it.</summary>
    public EventGroupLayerResult this[Int32 eventGroupID, Layer layer]
    {
        get
        {
            EventGroupLayerResult retval;
            if( !_Index.TryGetValue(new EventGroupIDLayerTuple(eventGroupID, layer), out retval) )
            {
                retval = new EventGroupLayerResult() { EventGroupID = eventGroupID, Layer = layer };
                this.Add(retval);
            }
            return retval;
        }
    }

    public bool Contains(Int32 eventGroupID, Layer layer)
    {
        return _Index.ContainsKey(new EventGroupIDLayerTuple(eventGroupID, layer));
    }

    #region Index Maintenance
    protected override void ClearItems()
    {
        _Index.Clear();
        base.ClearItems();
    }
    protected override void InsertItem(int index, EventGroupLayerResult item)
    {
        _Index.Add(new EventGroupIDLayerTuple(item.EventGroupID, item.Layer), item);
        base.InsertItem(index, item);
    }
    protected override void RemoveItem(int index)
    {
        _Index.Remove(new EventGroupIDLayerTuple(this[index].EventGroupID, this[index].Layer));
        base.RemoveItem(index);
    }
    protected override void SetItem(int index, EventGroupLayerResult item)
    {
        _Index.Remove(new EventGroupIDLayerTuple(this[index].EventGroupID, this[index].Layer));
        _Index.Add(new EventGroupIDLayerTuple(item.EventGroupID, item.Layer), item);
        base.SetItem(index, item);
    }
    #endregion
}

このコードにより、次のようにコレクション内の要素をすばやく作成/アクセス/変更できます。

eventGroupLayerResults[evt.GroupID, lyr].Sum += value;

コレクションをUIに簡単にバインドできるようにしながら。

ただし、それを行うには多数の ObservableCollection メソッドをオーバーライドする必要があったため、より良い解決策が引き続き評価されます。

于 2012-08-29T18:13:57.383 に答える