1

Hi I have two predicates. And I wonder if it is possible to join them together somehow into one? First:

Predicate<object> viewFilter = f =>
{
    ExternalUser u = f as ExternalUser;
    return u.AgentName.ToLower().StartsWith(agentName.ToLower());
};

Second:

Predicate<object> viewFilter = f =>
{
    ExternalUser u = f as ExternalUser;
    return u.ExternalLogin.ToLower().StartsWith(login.ToLower());
};

And this is how joined predicate should look like.

Predicate<object> viewFilter = f =>
{
    ExternalUser u = f as ExternalUser;
    return u.ExternalLogin.ToLower().StartsWith(login.ToLower()) && u.AgentName.ToLower().StartsWith(agentName.ToLower());
};

I need this for WPF data grid filter where grid source is ICollectionView. So after I've created my predicate I set it into filter like this:

private void FilterByLogin(ICollectionView view, string login)
{
    Predicate<object> viewFilter = f =>
    {
        ExternalUser u = f as ExternalUser;
        return u.ExternalLogin.ToLower().StartsWith(login.ToLower());
    };
    view.Filter = viewFilter;
}
xszaboj
  • 1,035
  • 7
  • 21
  • 1
    Aside from the question ; why do you use `as` without checking for `null` ? It implies you now for sure the type the just use a simple cast `(ExternalUser) f`. That way when for some obscure reason it'll fail you'll get an InvalidCastException rather than a NullReferenceException which is clearer about what is the problem – Sehnsucht Sep 28 '16 at 10:25
  • 1
    On a sidenote: Dont use `as` if you arent checking for null. Instead cast directly. `ExternalUser u =(ExternalUser) f;` – CSharpie Sep 28 '16 at 10:25
  • 3
    Possible duplicate of [Combine Multiple Predicates](http://stackoverflow.com/questions/1248232/combine-multiple-predicates) – Glen Thomas Sep 28 '16 at 10:28

2 Answers2

3

I would create two new methods:

public static Prediate<object> Cast<T>(Predicate<T> inner)
{
    return new Predicate<object>(o => inner((T)o));
}

public static Predicate<T> And<T>(Predicate<T> p1, Predicate<T> p2)
{
    return x => p1(x) && p2(x);
}

then you can remove the cast from your predicates and move it into the top-level:

Predicate<ExternalUser> first = u => u.AgentName.ToLower().StartsWith(agentName.ToLower());
Predicate<ExternalUser> second = u => u.ExternalLogin.ToLower().StartsWith(login.ToLower());

view.Filter = Cast(And(first, second));
Lee
  • 142,018
  • 20
  • 234
  • 287
1

It really should be as simple as this:

Predicate<object> viewFilter1 = f =>
{
    ExternalUser u = f as ExternalUser;
    return u.AgentName.ToLower().StartsWith(agentName.ToLower());
};

Predicate<object> viewFilter2 = f =>
{
    ExternalUser u = f as ExternalUser;
    return u.ExternalLogin.ToLower().StartsWith(login.ToLower());
};

Predicate<object> viewFilter = f => viewFilter1(f) && viewFilter2(f);
Enigmativity
  • 113,464
  • 11
  • 89
  • 172