首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >层次对象与AutoFixture

层次对象与AutoFixture
EN

Stack Overflow用户
提问于 2014-06-20 08:45:37
回答 1查看 1.9K关注 0票数 5

我已经实现了一个用于存储标记的类,标记集合必须是分级的,所以我的类是:

代码语言:javascript
复制
public class Tag
{
    public int Id { get; set; }
    public int Description { get; set; }
    public Tag ParentTag { get; set; }
    // … (methods for get children, add and remove children, etc.)
}

这样,根标记(用户希望能够拥有多个独立的树)没有父标记,而非根标记必须有父标记。

  1. 这是实现层次结构的好方法吗?我发现复合模式,但在我的领域,所有的标签都只是标签,对领域专家来说,父标记和子标记没有区别。
  2. 在测试中使用AutoFixture会出现问题;当我需要创建一个简单的标记时,它会引发以下错误: Failure:Ploeh.AutoFixture.ObjectCreationException__:AutoFixture无法创建Ploeh.AutoFixture.Kernel.SeededRequest类型的实例,因为遍历的对象图包含一个循环引用。

编辑:我读了用AutoFixture创建递归树,但情况不同:我只有一个类,而不是2个,我不希望自动夹具创建树,而只创建一个节点

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-20 09:00:16

这是实现层次结构的好方法吗?

我看到了三个问题,一个小问题,一个更严重一点,和一个明显的问题,在你的具体情况。

潜在问题:

1.让我们从一个小问题开始,它涉及属性的名称和它们的类型之间的关系。我建议一个名为ParentTag的属性应该是Tag类型本身。您将其声明为int (与Id一样)的事实表明,您应该调用属性ParentTagId而不是…或者将属性的类型更改为Tag

2.现在要谈到更严重的问题。我认为Desc指向一个直接的子标记。(如果一个标记可以有多个子标记,则显然为该属性选择了错误的类型。你需要一些收藏品。但这是另一个问题。)

存储父母和孩子的链接很容易导致不一致,如果你没有很好的注意。因此,最好不要为每个标签设置双向链接,而应该只存储一个方向的链接。

然而,这将使向相反方向遍历层次结构变得复杂。解决这个问题的一种方法是存储唯一的子链接;如果您想要找到T的父标记,那么首先通过递归遍历从根标记开始的层次结构来找到T,并不断地跟踪您所使用的“路径”;然后父标记将是路径中的倒数第二个标记。

3.现在是最直接的问题。例外情况暗示了这一点:

Ploeh.AutoFixture.ObjectCreationException…因为遍历的对象图包含一个循环引用。

使用Tag的当前实现,可以构建包含周期的标记层次结构。我猜你不想那样。

例如,标记C可以将P作为其父标记,尽管P已经是C的子标记。因此,如果您开始跟踪从C开始的ParentTag链,您将首先到达P,然后最终到达C,如果您继续运行,您会发现自己陷入了一个无限循环。

我不知道AutoFixture,但由于类似的原因,它可能无法处理具体的标记层次结构。

您应该使您的标记层次结构有向无圈图 -“无循环”是这里的重要部分。但是,使用当前的Tag类,您可以构建任何有向图;它不能保证不会有任何循环。

防止循环标记层次结构的方法:

1.ParentTag设置器中实现了对周期的检查:

代码语言:javascript
复制
public Tag ParentTag
{
    …
    set
    {
        if (!IsOrIsAncestorOf(value))
        {
            parentTag = value;
        }
        else
        {
            throw new ArgumentException("ParentTag", "would cause a cycle");
        }
    }
}
private Tag parentTag;

private bool IsOrIsAncestorOf(Tag other)
{
    return this == other || IsOrIsAncestorOf(other.Parent));
    //     ^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    //          Is   …   Or    …    IsAncestorOf
}

2.甚至更简单,让ParentTag readonly,这迫使您在构造函数中设置它。这将自动使构建循环标记层次结构变得不可能--如果您不相信,尝试它:

代码语言:javascript
复制
public Tag(Tag parentTag)
{
    this.parentTag = parentTag;
}

private readonly Tag parentTag;

public Tag ParentTag
{
    get
    {
        return parentTag;
    }
}

我建议第二种解决办法。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24323300

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档