4

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();
    }
}
Community
  • 1
  • 1
LotuX
  • 374
  • 1
  • 11
  • 30
  • Did you include the namespace of the method extension in in the file that relies on that method? – Scott Nimrod Nov 04 '15 at 17:58
  • Also, are you using namespace aliasing? – Ian P Nov 04 '15 at 17:58
  • In the first case you still have an object t while in the second case you cast f to a string. – jdweng Nov 04 '15 at 17:59
  • 2
    You need to show your extension method RemoveDiacritics. What type is it expecting? ToLower is an extension method of string if your extension method does not begin with (this string something... then that would be why. – Stephen Brickner Nov 04 '15 at 17:59
  • As you can see the extension method expect a string. For the namespace it is part of the same project so it should not be an issue as both classes are in the same namespace. – LotuX Nov 05 '15 at 08:07
  • What is the Where() method in `queryable.Where(predicate, values)`? It looks like `predicate` is a string containing C#-like code, how do you parse and compile it later? – FarmerBob Nov 05 '15 at 08:39
  • The Where() is coming from `System.Linq.Dynamic`, define in the `DynamicQueryable` static object: `public static IQueryable Where(this IQueryable source, string predicate, params object[] values);`. As for the object queryable this is coming from a input function parameter declared like this `IQueryable queryable`. So the type is generic – LotuX Nov 05 '15 at 09:29
  • Actually I think I now know the reason why. It is indeed probably because of the namespace, as the extension method is actually call inside the `System.Linq.Dynamic`, which probably doesn't know this method even exist. The question now is: Is there a way to day it without touching the library of `System.Linq.Dynamic`? – LotuX Nov 05 '15 at 10:49
  • If you read the whole answer that you linked the answerer explains why this doesn't work. The only way to get this to work is to change the collation of your column in SQL and then simply use `==` in C#. – Jonathan Dickinson Nov 06 '15 at 12:41
  • You define the extension method on String, not string. Did you try changing your typecast to (String)? – Andy Isbell Nov 21 '15 at 08:10
  • @AndyIsbell [string is an Alias for String](http://stackoverflow.com/a/7077/4632606) – ZwoRmi Feb 25 '16 at 16:44

2 Answers2

3

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();
Mikael Nitell
  • 1,069
  • 6
  • 16
0
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.

ToXinE
  • 308
  • 2
  • 13