【问题标题】:How to automatically set the parent object in a child property with autofixture如何使用 autofixture 在子属性中自动设置父对象
【发布时间】:2013-06-25 14:01:08
【问题描述】:

我想使用 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。 对于包含该对象的属性类型的所有属性,将它们设置为父对象。换句话说,触发递归保护的类型的所有属性都将它们设置为创建层次结构中的最后一个对象。

【问题讨论】:

  • 您可以更改类的 API 吗?这里提出的设计不仅对 AutoFixture 来说难以处理,而且通常会给您和您的团队成员带来永久的痛苦。

标签: c# autofixture


【解决方案1】:

我的回答假设

  1. 如果您直接创建 B,B.Parent 应该是 null。
  2. B.Parent 应该设置为包含它的A 的实例,如果您创建A。

在使用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)));

【讨论】:

  • 感谢您的回答,我绝对可以使用它,但我正在考虑一种更通用的方式,而无需指定类型 A 和 B 甚至属性 Children。对于包含该对象的属性类型的所有属性,将它们设置为父对象。换句话说,触发递归保护的类型的所有属性都将它们设置为创建层次结构中的最后一个对象。
  • @hokkos: 如果一个属性触发了一个类型为other的属性的递归保护,而不是层次结构中的最后一个对象呢? A.Children(of type B) -&gt; B.Children(of type C) -&gt; c.GrandFather(of type A)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多