Reputation: 1669
I have a list of objects like this (I am using .NET 3.5)
public class MyObjects
{
public object Name { get; set; }
public bool Case { get; set; }
}
List<MyObjects> test = new List<MyObjects> {
new MyObjects { Name = "one" },
new MyObjects { Name = "two" },
new MyObjects { Name = "three" },
new MyObjects { Name = "four" },
new MyObjects { Name = "one1" },
new MyObjects { Name = "two1" },
new MyObjects { Name = "three1" },
new MyObjects { Name = "four1" },
new MyObjects { Name = "one2" },
new MyObjects { Name = "two2" },
new MyObjects { Name = "three2" },
new MyObjects { Name = "four2" },
};
Now I try to search in the list using Linq. This is working as expected
var tmp = test
.Select(p => p.Name)
.Where(x => x.ToString().Contains("One", StringComparison.InvariantCultureIgnoreCase))
;
Using Dynamic Linq, this also works as expected
var dtmp = test.AsQueryable()
.Select(p => p.Name)
.Where("ToString().Contains(@0)", "one")
;
However, when trying to use case (in)sensitive, the dynamic fails.
var dtmp2 = test.AsQueryable()
.Select(p => p.Name)
.Where("ToString().Contains(@0, @1)", "one", StringComparison.InvariantCultureIgnoreCase)
;
The error is
No applicable method 'Contains' exists in type 'String'
My first attempt was to write a Contains() extension like this
public static bool Contains(this string source, string toCheck, StringComparison comp)
{
return source.IndexOf(toCheck, comp) >= 0;
}
Appears that Dynamic Linq isn't aware of my extension. I discovered (according to this) https://social.msdn.microsoft.com/Forums/en-US/39763339-1700-486f-9800-badd257e921e/custom-extension-methods-and-dynamic-linq-dynamic-expression-api?forum=linqprojectgeneral
that Dynamic Linq cannot uses (static) extension very easily.
So either:
Transform extension in a normal method. However, how can I do this for every ToString(), is it possible or should I write a method in MyObject then use linq with specific objects ?
Modify the Dynamic Library code to accept hard coded (my)static extensions.
Other suggestions?
Note: I could use a simple if/else for case sensitive with two dynamics but I prefer to solve the dynamic way since my app use some complex filtering.
Thank you in advance,
Upvotes: 2
Views: 9584
Reputation: 9830
Did you try using System.Linq.Dynamic.Core because it seems that this library can handle your example c# code.
Upvotes: 0
Reputation: 535
If your application needs dynamic filter capabilities, I would recommend having the caller pass a predicate.
This allows for a separation of concerns and easier unit testing.
Also, no need for a IF/ELSE statement when the caller passes a predicate.
var predicate = new Predicate<string>(str => str.Contains("one"));
var tmp = test.Select(p => p.Name).Where(predicate);
Upvotes: 1