为类的集合提供强大的一致性检查

时间:2014-05-22 21:49:55

标签: c# .net winforms

给出我正在做的事情的背景知识:

我有一个程序,允许用户修改和创建一般校准。校准内部包括组。组根据它们执行的分析类型而不同。这些组还包括光谱集,每组包含仅一个分子的数据。在这些组中还包括不同浓度的光谱数据。每个光谱数据是一组离散数据,由其分辨率(每个点之间的x轴空间)和其光谱范围(x轴范围)指定。

构建这些校准文件的主要方面之一是保持每组中所有光谱数据的分辨率和光谱范围一致。这意味着除非光谱数据与其余光谱数据匹配,否则无法添加光谱数据。此外,如果用户删除所有光谱数据,则会重置分辨率和范围,从而允许将任何范围或分辨率的光谱数据添加到校准中。

问题是:如何提供一种有效的方法来防止将光谱数据添加到与当前分辨率和光谱范围不匹配的校准中?

以下是校准类的一般说明。这是一个非常笼统的描述,包含解释我要做的事情所需的唯一信息。

class calibration
{
    List<Group> groups;
}


class Group
{
    List<SpectralSet> sets;
}

class SpectralSet
{
    List<SpectraData> spectras;
}

class SpectraData
{
    double firstXPoint;
    double lastXPoint;
    double resolution;
    double[] Ypoints; 
}

2 个答案:

答案 0 :(得分:0)

我确定您可以应用各种花哨的设计模式来执行您提到的规则。

但是,为了简单起见,我只是使用calibration方法将逻辑封装在AddGroup类中,该方法验证添加的group符合校准的标准。要求。同样,我会为AddSpectralSet类创建一个group方法,作为sets集合的守门员。

此时,根据这些内容发生变化的频率,我会考虑将groups集合和sets集合公开为ReadOnlyCollection,以确保代码不会尝试不使用规定的方法添加项目。

希望这有帮助。

答案 1 :(得分:0)

您的方法可能会略有不同,但这里概述了如何实现这一目标。您需要执行以下操作:

  • 仅公开不可变的公共集合属性以及Add方法,以便您可以进行自己的验证。

例如,您不想这样做:

class Group
{
    public List<SpectralSet> sets;
}

因为那时任何人都可以myGroup.sets.Add(mySet),而没有机会对集合进行任何验证。实现这一目标的一种常见模式如下:

class Group
{
    private List<SpectralSet> _sets;
    public IEnumerable<SpectralSet> Sets { get { return _sets; } }

    public void Add(SpectralSet set)
    {
        //Do validation here, throw an exception or whatever you want to do if the set isn't valid
        _sets.Add(set);
    }

    //Have a similar Remove method
}
  • 存储数据必须匹配的条件

我不太清楚光谱范围是什么,所以我只是以分辨率为例。您可以将其扩展到任何范围标准。至少有三种可能的方法可以做到这一点:

  1. 构造一个类时,将它传递给构造函数中允许的解析,并使其成为不可变的。
  2. 添加和删除时,根据需要更新允许的分辨率。
  3. 不要明确存储分辨率,每次添加或删除时都要计算分辨率。
  4. 其中,选项1是迄今为止最简单的选项。当你能够尽可能地保持不变时,生活总是容易得多。所以你会做类似的事情:

    class Group
    {
        private List<SpectralSet> _sets;
        public IEnumerable<SpectralSet> Sets { get { return _sets; } }
        public readonly double Resolution;
    
        public Group(double resolution)
        {
            Resolution = resolution;
        }
    
        public void Add(SpectralSet set)
        {
            if(set.Resolution != resolution)
                //Throw an Exception here, or however you want to handle invalid data
            _sets.Add(set);
        }
    
        //Have a similar Remove method
    }
    

    按照此示例,您包含的每个类都需要一个具有相同逻辑类型的Resolution参数,只需检查您尝试添加的任何直接子项的Resolution。同样适用于光谱范围。

    如果清除了所有数据,您还希望能够更改允许的分辨率。最简单的方法是在清除数据时创建新对象,而不是仅清除现有对象中的集合。

    • SpectraData不可变

    如果您可以从其中一个精心设计的集合中获取SpectraData并随意更改它,那么这一切都毫无用处。使任何需要验证的东西都是不可变的,只允许在构造时设置它。如果您有要求不这样做,您需要仔细考虑如何允许更改它。