Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>To add a bit of extra information on how I solved this problem I thought it'd be useful to post an associative answer.</p> <p>The "standard" way of chaining method calls is to return an instance of the same class upon which subsiquent method calls can be made.</p> <p>My original code did this by directly returning <code>this</code>, however, since my methods were mutating fields by building up collections of <code>Func&lt;T&gt;</code>'s, this left the consumer open to threading and reentry issues.</p> <p>To solve this problem I decided to impliment <code>ICloneable</code> and have it return a new instance of the same class via <code>object.MemberwiseClone()</code>. This shallow-clone works fine my this case because the fields being added to were value types which are copied over during the shallw-clone process.</p> <p>Each public method in my class now executes the instances <code>Clone</code> method and updates the private fields before returning the clone such that:</p> <pre><code>public class ServiceManager : IServiceManager { /// &lt;summary&gt; /// A collection of Funcs to execute if the service fails. /// &lt;/summary&gt; private readonly List&lt;Func&lt;dynamic&gt;&gt; failedFuncs = new List&lt;Func&lt;dynamic&gt;&gt;(); /// &lt;summary&gt; /// The number of times the service call has been attempted. /// &lt;/summary&gt; private int count; /// &lt;summary&gt; /// The number of times to re-try the service if it fails. /// &lt;/summary&gt; private int attemptsAllowed; /// &lt;summary&gt; /// Gets or sets a value indicating whether failed. /// &lt;/summary&gt; public bool Failed { get; set; } /// &lt;summary&gt; /// Gets or sets the service func. /// &lt;/summary&gt; private Func&lt;dynamic&gt; ServiceFunc { get; set; } /// &lt;summary&gt; /// Gets or sets the result implimentation. /// &lt;/summary&gt; private dynamic ResultImplimentation { get; set; } /// &lt;summary&gt; /// Gets the results. /// &lt;/summary&gt; /// &lt;typeparam name="TResult"&gt; /// The result. /// &lt;/typeparam&gt; /// &lt;returns&gt; /// The TResult. /// &lt;/returns&gt; public TResult Result&lt;TResult&gt;() { var result = this.Execute&lt;TResult&gt;(); return result; } /// &lt;summary&gt; /// The execute service. /// &lt;/summary&gt; /// &lt;typeparam name="TResult"&gt; /// The result. /// &lt;/typeparam&gt; /// &lt;param name="action"&gt; /// The action. /// &lt;/param&gt; /// &lt;param name="attempts"&gt; /// The attempts. /// &lt;/param&gt; /// &lt;returns&gt; /// ServiceManager.IServiceManager. /// &lt;/returns&gt; public IServiceManager ExecuteService&lt;TResult&gt;( Func&lt;TResult&gt; action, int attempts) { var serviceManager = (ServiceManager)this.Clone(); serviceManager.ServiceFunc = (dynamic)action; serviceManager.attemptsAllowed = attempts; return serviceManager; } /// &lt;summary&gt; /// The if service fails. /// &lt;/summary&gt; /// &lt;typeparam name="TResult"&gt; /// The result. /// &lt;/typeparam&gt; /// &lt;param name="action"&gt; /// The action. /// &lt;/param&gt; /// &lt;returns&gt; /// ServiceManager.IServiceManager`1[TResult -&amp;gt; TResult]. /// &lt;/returns&gt; public IServiceManager IfServiceFailsThen&lt;TResult&gt;( Func&lt;TResult&gt; action) { var serviceManager = (ServiceManager)this.Clone(); serviceManager.failedFuncs.Add((dynamic)action); return serviceManager; } /// &lt;summary&gt; /// Clones the current instance of ServiceManager. /// &lt;/summary&gt; /// &lt;returns&gt; /// An object reprisenting a clone of the current ServiceManager. /// &lt;/returns&gt; public object Clone() { return this.MemberwiseClone(); } } </code></pre> <p>Private methods removed for brevity. Full source code can be found here:</p> <p><a href="https://github.com/JamieDixon/ServiceManager" rel="nofollow">https://github.com/JamieDixon/ServiceManager</a></p>
 

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