0

我的任务是将“表驱动”程序转换为面向对象的程序。过去一切都是通过在内存中创建大表、添加和删除行和列以及将所有内容解析为字符串来完成的。这太可怕了。这些表直接反映了存储所有内容的底层数据库的结构。

对于这个问题,我有Layer大约 100 个属性的Event对象,并且我有大约 20 个属性的对象。然后,我为每对有一组大约 10 个计算值Layer/Event。这些被存储为第三个表,外键指向其他每个表。

我想创建一个适当的面向对象的类来存储这些数据并像在字典中一样快速访问值。

我的第一个想法是在字典中索引结果,但我觉得它的使用是不直观的:

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.Layer, Key.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) 时间来稍后查找特定的事件/层结果,除非我开始添加所有这些额外的包袱,例如监视集合的自定义包装类添加事件并索引字典中的集合项, ETC。

我无法想象其他人每次想要将由两个外键索引的简单表转换为对象模型时都会经历所有这些。是否有一种我不知道的标准方法或数据结构可以使这种数据集易于使用?

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 回答