title: How can I use custom ISpecimenBuilders with OmitOnRecursionBehavior?
body: <p>
  How can I use custom <code>ISpecimenBuilder</code> instances along with the <code>OmitOnRecursionBehavior</code> which I want applied globally to all fixture-created objects?</p>
  
  <p>I'm working with an EF Code First model with a foul-smelling circular reference that, for the purposes of this question, cannot be eliminated:</p>
  
  <pre class="lang-cs prettyprint-override"><code>public class Parent {
      public string Name { get; set; }
      public int Age { get; set; }
      public virtual Child Child { get; set; }
  }
  
  public class Child {
      public string Name { get; set; }
      public int Age { get; set; }
      public virtual Parent Parent { get; set; }
  }
  </code></pre>
  
  <p>I'm familiar with the technique for side-stepping circular references, as in this passing test:</p>
  
  <pre class="lang-cs prettyprint-override"><code>[Theory, AutoData]
  public void CanCreatePatientGraphWithAutoFixtureManually(Fixture fixture)
  {
      //fixture.Customizations.Add(new ParentSpecimenBuilder());
      //fixture.Customizations.Add(new ChildSpecimenBuilder());
      fixture.Behaviors.OfType&lt;ThrowingRecursionBehavior&gt;().ToList()
                       .ForEach(b =&gt; fixture.Behaviors.Remove(b));
      fixture.Behaviors.Add(new OmitOnRecursionBehavior());
      fixture.Behaviors.Add(new TracingBehavior());
      var parent = fixture.Create&lt;Parent&gt;();
      parent.Should().NotBeNull();
      parent.Child.Should().NotBeNull();
      parent.Child.Parent.Should().BeNull();
  }
  </code></pre>
  
  <p>But if either/both customizations are uncommented, I get an exception:</p>
  
  <pre class="lang-cs prettyprint-override"><code>System.InvalidCastException: Unable to cast object of type
  'Ploeh.AutoFixture.Kernel.OmitSpecimen' to type 'CircularReference.Parent'.
  </code></pre>
  
  <p>The failing cast is occurring in my <code>ISpecimenBuilder</code> implementations (shown at the bottom of this question) when I call on the <code>ISpecimenContext</code> to resolve <code>Parent</code> and the request is coming from the <code>Child</code> being resolved. I could guard against the request coming from the <code>Child</code> resolving operation like this:</p>
  
  <pre class="lang-cs prettyprint-override"><code>//...
  &amp;&amp; propertyInfo.ReflectedType != typeof(Child)
  //...
  </code></pre>
  
  <p>But, that seems to pollute the <code>ISpecimenBuilder</code> implementation with knowledge of 'who' might be making the request. Also, it seems to duplicate the work that the 'global' <code>OmitOnRecursionBehavior</code> is meant to do.</p>
  
  <p>I want to use the <code>ISpecimenBuilder</code> instances because I have other things to customize besides handling the circular reference. I've spent a lot of time looking for examples of a scenario like this here on SO and also on <a href="http://blog.ploeh.dk/tags.html#AutoFixture-ref">Ploeh</a> but I haven't found anything yet that discusses the <strong>combination of behaviors and customizations</strong>.  It's important that the solution be one that I can encapsulate with <code>ICustomization</code>, rather than lines and lines in the test setup of </p>
  
  <pre class="lang-cs prettyprint-override"><code>//...
  fixture.ActLikeThis(new SpecialBehavior())
         .WhenGiven(typeof (Parent))
         .AndDoNotEvenThinkAboutBuilding(typeof(Child))
         .UnlessParentIsNull()
  //...
  </code></pre>
  
  <p>...because ultimately I want to extend an <code>[AutoData]</code> attribute for tests.</p>
  
  <p>What follows are my <code>ISpecimenBuilder</code> implementations and the output of the <code>TracingBehavior</code> for the failing test:</p>
  
  <pre class="lang-cs prettyprint-override"><code>public class ChildSpecimenBuilder : ISpecimenBuilder
  {
      public object Create(object request, ISpecimenContext context)
      {
          var propertyInfo = request as PropertyInfo;
          return propertyInfo != null
                 &amp;&amp; propertyInfo.PropertyType == typeof(Child)
                     ? Resolve(context)
                     : new NoSpecimen(request);
      }
  
      private static object Resolve(ISpecimenContext context)
      {
          var child = (Child) context.Resolve(typeof (Child));
          child.Name = context.Resolve(typeof (string)).ToString().ToLowerInvariant();
          child.Age = Math.Min(17, (int) context.Resolve(typeof (int)));
          return child;
      }
  }
  
  public class ParentSpecimenBuilder : ISpecimenBuilder
  {
      public object Create(object request, ISpecimenContext context)
      {
          var propertyInfo = request as PropertyInfo;
          return propertyInfo != null
                 &amp;&amp; propertyInfo.PropertyType == typeof (Parent)
                     ? Resolve(context)
                     : new NoSpecimen(request);
      }
  
      private static object Resolve(ISpecimenContext context)
      {
          var parent = (Parent) context.Resolve(typeof (Parent));
          parent.Name = context.Resolve(typeof (string)).ToString().ToUpperInvariant();
          parent.Age = Math.Max(18, (int) context.Resolve(typeof (int)));
          return parent;
      }
  }
  
  CanCreatePatientGraphWithAutoFixtureManually(fixture: Ploeh.AutoFixture.Fixture) : Failed  Requested: Ploeh.AutoFixture.Kernel.SeededRequest
      Requested: CircularReference.Parent
        Requested: System.String Name
          Requested: Ploeh.AutoFixture.Kernel.SeededRequest
            Requested: System.String
            Created: 38ab48f4-b071-40f0-b713-ef9d4c825a85
          Created: Name38ab48f4-b071-40f0-b713-ef9d4c825a85
        Created: Name38ab48f4-b071-40f0-b713-ef9d4c825a85
        Requested: Int32 Age
          Requested: Ploeh.AutoFixture.Kernel.SeededRequest
            Requested: System.Int32
            Created: 9
          Created: 9
        Created: 9
        Requested: CircularReference.Child Child
          Requested: Ploeh.AutoFixture.Kernel.SeededRequest
            Requested: CircularReference.Child
              Requested: System.String Name
                Requested: Ploeh.AutoFixture.Kernel.SeededRequest
                  Requested: System.String
                  Created: 1f5ca160-b211-4f82-871f-11882dbcf00d
                Created: Name1f5ca160-b211-4f82-871f-11882dbcf00d
              Created: Name1f5ca160-b211-4f82-871f-11882dbcf00d
              Requested: Int32 Age
                Requested: Ploeh.AutoFixture.Kernel.SeededRequest
                  Requested: System.Int32
                  Created: 120
                Created: 120
              Created: 120
              Requested: CircularReference.Parent Parent
                Requested: CircularReference.Parent
                Created: Ploeh.AutoFixture.Kernel.OmitSpecimen
  
  System.InvalidCastException: Unable to cast object of type 'Ploeh.AutoFixture.Kernel.OmitSpecimen' to type 'CircularReference.Parent'.
  </code></pre>