简体   繁体   中英

Use C# extension method as predicate in linq query

I implemented the extension method to normalize a string described in this post: LINQ Where Ignore Accentuation and Case

This method work like a charm if I do things like this:

employee.AsQueryable().Where(t=>t.Text.ToLower().RemoveDiacritics().Contains("ced"));

Now, I want to use it more generically by generating the predicate of the where clause dynamically.

var values = filters.Select(f => f.Value is string && f.IgnoreAccent
                               ?((string)f.Value).RemoveDiacritics()
                               :f.Value).ToArray();

// Create a predicate expression
string predicate = filter.ToExpression(filters);

// Use the Where method of Dynamic Linq to filter the data
queryable = queryable.Where(predicate, values);

The predicate will look like this:

(Text.ToLower().RemoveDiacritics().Contains(@0))

For an unknown reason, when executed I got the following error message:

No applicable method 'RemoveDiacritics' exists in type 'String'

But, this method actually works fine if I use it elsewhere.

Any ideas what is wrong here?

Note that the ToLower() works like a charm in this situation.

Thanks in advance for your help!

EDIT

Here is the definition of the extension method:

public static class StringExtension
{
    public static string RemoveDiacritics(this String s)
    {
        String normalizedString = s.Normalize(NormalizationForm.FormD);
        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < normalizedString.Length; i++)
        {
            Char c = normalizedString[i];

            if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
                stringBuilder.Append(c);
        }

        return stringBuilder.ToString();
    }
}

Dynamic Linq does not support extension methods. The reason for this is that Dynamic Linq uses reflection, and it is really hard to find the implementation of the extension method, and call it using reflection. So the authors of dynamic Linq didn't bother with it.

So, you have to call the extension method like a regular static method:

var values = filters.Select(f => f.Value is string && f.IgnoreAccent
                           ?StringExtensions.RemoveDiacritics((string)f.Value)
                           :f.Value).ToArray();
employee.AsQueryable().Where(t=>t.Text.ToLower().RemoveDiacritics().Contains("ced"));

can be replaced with

employee.AsQueryable().Where(t=>t.Text.Equals("ced", StringComparison.OrdinalIgnoreCase));

which is faster and doesn't bother with case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM