0

I have some code which I would like to refactor, but I don't know how to do it. The code in question repeats itself, except for an expression which varies.

The code:

Expression<Func<SearchModel, bool>> first = null;
if (first == null)
{
    if (equal && not)
        first = c1 => c1.Address.PostalCode != newTerm;
    else if (equal)
        first = c1 => c1.Address.PostalCode == newTerm;
    else if (not)
        first = c1 => !c1.Address.PostalCode.Contains(newTerm);
    else
        first = c1 => c1.Address.PostalCode.Contains(newTerm);
}
else
{
    if (equal && not)
        first = first.Or(c1 => c1.Address.PostalCode != newTerm);
    else if (equal)
        first = first.Or(c1 => c1.Address.PostalCode == newTerm);
    else if (not)
        first = first.Or(c1 => !c1.Address.PostalCode.Contains(newTerm));
    else
        first = first.Or(c1 => c1.Address.PostalCode.Contains(newTerm));
}

equal and not are Boolean values.

This code is repeated several times, except that c1.Address.PostalCode could be c1.Address.City, or even c1.User.PhoneNumber.

Can I somehow refactor this so that I can use a method and inject the c1.Address.PostalCode? Something like this:

if (equal && not)
    first = c1 => <variable> != newTerm;
...
else if (not)
    first = c1 => !<variable>.Contains(newTerm);

It looks like this post is what I'm looking for:

Property Name to Lambda Expression C#

But I need to go a little further, because the Address property is a class itself, which of course has properties, one of which is PostalCode.

Servy
  • 202,030
  • 26
  • 332
  • 449
Marc Levesque
  • 154
  • 1
  • 6
  • You could use reflection but you would need to have some more if statement if the property type is a collection or not because of the contains. – Franck Jan 11 '18 at 16:29
  • @Franck The code expects the property value to be a string, not a collection. It's doing a string contains check. – Servy Jan 11 '18 at 16:42
  • @Servy Thanks for the link. Indeed that's what I was looking for. (It would have helped had I known what to search!) I've managed to pass my expression into a method, but I'm unsure what to do with it. I'm passing a `Expression>` into the method. When I debug and watch the value, it shows it is `{smodel => smodel.User.ContactLastName}`, but I don't know how to use that in my code `first = c1 => c1.User.ContactLastName == newTerm`. – Marc Levesque Jan 11 '18 at 20:39
  • There's an example right in the answer in the duplicate of how to use the method. – Servy Jan 11 '18 at 20:43
  • @Servy I don't see it. I've copied all your code, using the same variable names, and I'm passing "magic" to my method. I don't see how to use "magic" once inside the method though. – Marc Levesque Jan 11 '18 at 20:51
  • @MarcLevesque You assign it to `first`. – Servy Jan 11 '18 at 20:54
  • @Servy That won't work because first is type `Expression>` and magic is type `Expression>`. – Marc Levesque Jan 11 '18 at 21:07
  • @MarcLevesque The reason you're calling compose is to turn your mapping from a search model to a property value and your mapping from a property value to a boolean into a mapping from a search model to a boolean. So the return value of `Compose` *will* be an `Expression>` for you. – Servy Jan 11 '18 at 21:25

0 Answers0