如何使用自动混合在子属性中自动设置父对象

时间:2013-06-25 14:01:08

标签: c# autofixture

我想使用自动混合来创建一个对象图,其中子对象具有父对象的引用。例如:

class A
{
  public List<B> Children { get; set; }
}

class B
{
  public A Parent { get; set; }
}

我尝试创建一个处理递归的行为,但我不知道如何将父对象作为属性的内容发出。

public class AutoParentOnRecursionBehavior : ISpecimenBuilderTransformation
{
    public ISpecimenBuilder Transform(ISpecimenBuilder builder)
    {
        if (builder == null)
            throw new ArgumentNullException("builder");

        return new RecursionGuard(builder, new AutoParentOnRecursionHandler());
    }
}

public class AutoParentOnRecursionHandler : IRecursionHandler
{
    public object HandleRecursiveRequest(
        object request,
        IEnumerable<object> recordedRequests)
    {
        object handleRecursiveRequest = recordedRequests.First(x => x.Equals(request));
        return ....
    }
}

感谢。

编辑: 我正在考虑一种通用的方法,而不必指定类型A和B甚至属性Children。 对于包含该对象的属性类型的所有属性,请将它们设置为父对象。换句话说,触发递归保护的类型的所有属性都将它们设置为创建层次结构中的最后一个对象。

1 个答案:

答案 0 :(得分:2)

我的回答是假设

    如果您直接创建B.Parent,则
  1. null应为B
  2. 如果您创建B.Parent,则应将
  3. A设置为包含它的A实例。
  4. 使用PostProcessorFor时,可以通过以下相当简单的自定义来实现:

    fixture.Customize<B>(c => c.Without(x => x.Parent));
    fixture.PostProcessorFor<A>(a => { foreach(var b in a.Children) b.Parent = a; });
    

    有些断言要说明结果:

    var b = fixture.Create<B>();
    Assert.Null(b.Parent);
    
    var a = fixture.Create<A>();
    Assert.True(a.Children.All(b => ReferenceEquals(b.Parent, a)));