Note that there are some explanatory texts on larger screens.

plurals
  1. POBuilder design pattern with inheritance: is there a better way?
    text
    copied!<p>I'm creating a series of builders to clean up the syntax which creates domain classes for my mocks as part of improving our overall unit tests. My builders essentially populate a domain class (such as a <code>Schedule</code>) with some values determined by invoking the appropriate <code>WithXXX</code> and chaining them together.</p> <p>I've encountered some commonality amongst my builders and I want to abstract that away into a base class to increase code reuse. Unfortunately what I end up with looks like:</p> <pre><code>public abstract class BaseBuilder&lt;T,BLDR&gt; where BLDR : BaseBuilder&lt;T,BLDR&gt; where T : new() { public abstract T Build(); protected int Id { get; private set; } protected abstract BLDR This { get; } public BLDR WithId(int id) { Id = id; return This; } } </code></pre> <p>Take special note of the <code>protected abstract BLDR This { get; }</code>.</p> <p>A sample implementation of a domain class builder is:</p> <pre><code>public class ScheduleIntervalBuilder : BaseBuilder&lt;ScheduleInterval,ScheduleIntervalBuilder&gt; { private int _scheduleId; // ... // UG! here's the problem: protected override ScheduleIntervalBuilder This { get { return this; } } public override ScheduleInterval Build() { return new ScheduleInterval { Id = base.Id, ScheduleId = _scheduleId // ... }; } public ScheduleIntervalBuilder WithScheduleId(int scheduleId) { _scheduleId = scheduleId; return this; } // ... } </code></pre> <p>Because BLDR is not of type BaseBuilder I cannot use <code>return this</code> in the <code>WithId(int)</code> method of <code>BaseBuilder</code>.</p> <p>Is exposing the child type with the property <code>abstract BLDR This { get; }</code> my only option here, or am I missing some syntax trick?</p> <p>Update (since I can show why I'm doing this a bit more clearly):</p> <p>The end result is to have builders that build profiled domain classes that one would expect to retrieve from the database in a [programmer] readable format. There's nothing wrong with...</p> <pre><code>mock.Expect(m =&gt; m.Select(It.IsAny&lt;int&gt;())).Returns( new Schedule { ScheduleId = 1 // ... } ); </code></pre> <p>as that's pretty readable already. The alternative builder syntax is:</p> <pre><code>mock.Expect(m =&gt; m.Select(It.IsAny&lt;int&gt;())).Returns( new ScheduleBuilder() .WithId(1) // ... .Build() ); </code></pre> <p>the advantage I'm looking for out of using builders (and implementing all these <code>WithXXX</code> methods) is to abstract away complex property creation (automatically expand our database lookup values with the correct <code>Lookup.KnownValues</code> without hitting the database obviously) and having the builder provide commonly reusable test profiles for domain classes...</p> <pre><code>mock.Expect(m =&gt; m.Select(It.IsAny&lt;int&gt;())).Returns( new ScheduleBuilder() .AsOneDay() .Build() ); </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload