Note that there are some explanatory texts on larger screens.

plurals
  1. POCreate a reusable "meta-predicate" function accepting lambda operand parameters
    text
    copied!<p>Is it possible to create a "meta-predicate" by writing a a function that takes 2 (or 4 if necessary) lambdas which represent the left and right side properties (operands) and have it generate an predicate. Something like the following code sample:</p> <pre><code>public Expression&lt;Func&lt;Something,bool&gt;&gt; StringEquals&lt;Something&gt;(Expression&lt;Something&gt; leftOperand, Expression&lt;Something&gt; leftOperandSelector){ return (rightOperandSelector, leftOperandSelector) =&gt; ( (rightOperandSelector == leftOperandSelector) || ( string.IsNullOrEmpty(rightOperandSelector) &amp;&amp; string.IsNullOrEmpty(leftOperandSelector) ) ); } </code></pre> <p>OR:</p> <pre><code>public Expression&lt;Func&lt;Something,bool&gt;&gt; DatesActive&lt;Something&gt;(Expression&lt;Something&gt; startDateOperandSelector, Expression&lt;Something&gt; endDateOperandSelector){ return (startDateOperandSelector, endDateOperandSelector) =&gt; ( (startDatePropertySelector &gt;= DateTime.Now) &amp;&amp; (endDatePropertySelector &lt;= DateTime.Now) ); } </code></pre> <p>Where <em>SomeStringProperty</em> for each side or <em>startDatePropertySelector</em> or <em>endDatePropertySelector</em> is defined by a lambda? I have not figured out how to dynamically pass the Operand of the predicate expression.</p> <p>Ideally I would like to be able to inline it like this:</p> <pre><code>return new Expression&lt;Func&lt;Request,bool&gt;&gt;[]{ r =&gt; (r.Id != request.Id) &amp;&amp; (!r.Reviewed), StringEquals(r =&gt; r.VendorName, request=&gt;request.VendorName), NotExpired(r =&gt; r.ContractStart, request=&gt;request.ContractEnd), ... }; </code></pre> <p>*<em>Does someone have an idea on the best way to approach this? My interest is in creating "meta"-expressions for easy use where I am using the same expression repeatedly over multiple properties. Concrete example is given just for reference/explanation. Very open to knowing if this is silly and if there is a better approach, happy to learn. *</em></p> <p>More background below if desired.</p> <p><strong>Background:</strong> After a simpler form of this Expression was in place I was forced to refactor to handle the fact that EntityFramework doesn't treat equality how you would expect in that instead of interpreting C# like the following: <code>(rightSide.SomeStringProperty == leftSide.SomeStringProperty)</code> as a two part SQL expression like this</p> <pre><code>( (rightSide.SomeStringProperty IS NULL AND leftSide.SomeStringProperty IS NULL) OR (rightSide.SomeStringProperty = leftSide.SomeStringProperty) ) </code></pre> <p>it more literally tranlates it as:</p> <pre><code>(rightSide.SomeStringProperty = leftSide.SomeStringProperty) </code></pre> <p>which of course will not return values for where both sides are null. Apparently this has been corrected in EF6 (<strong>Correction</strong>: @Slauma points out this is available in EF5 via the UseCSharpNullComparisonBehavior. I am using EF4 and cannot upgrade for this release.)</p> <p>I want to avoid more repetitive code like the following:</p> <pre><code> var where = new Expression&lt;Func&lt;Request,bool&gt;&gt;[]{ r =&gt; (r.Id != request.Id) &amp;&amp; (!r.Reviewed) &amp;&amp; ( (r.Address == request.Address) || (string.IsNullOrEmpty(r.Address) &amp;&amp; string.IsNullOrEmpty(request.Address)) ) &amp;&amp; ( (r.City == request.City) || (string.IsNullOrEmpty(r.City) &amp;&amp; string.IsNullOrEmpty(request.City)) ) &amp;&amp; ( (r.Province == request.Province) || (string.IsNullOrEmpty(r.Province) &amp;&amp; string.IsNullOrEmpty(request.Province)) ) &amp;&amp; ( (r.PostalCode == request.PostalCode) || (string.IsNullOrEmpty(r.PostalCode) &amp;&amp; string.IsNullOrEmpty(request.PostalCode)) ) &amp;&amp; ( (r.Website == request.Website) || (string.IsNullOrEmpty(r.Website) &amp;&amp; string.IsNullOrEmpty(request.Website)) ) }; </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