There's the problem I made an Extension method to IQueryable and I want to get property name and value to do a select on it the thing is that I am using Expression tree and try to search rows by the use of Contain() method which is needs a parameter of type string to do the job. my code is doing well while I do the search over string properties but I want this method to do the search on other types like int, decimal, datetime and even booleans so I need to get the property cast it to string and search for the matching values.
what I tried so far is:
private static readonly MethodInfo _tostring = typeof(Object).GetMethod("ToString") ?? throw new Exception("Cannot create Method");
public static IQueryable<T> Search<T>(this IQueryable<T> items, string propertyName, string filterValue)
{
MethodInfo _compare =
(((Expression<Func<string, bool>>)(s => s.Contains("aa"))).Body as MethodCallExpression ?? throw new Exception("Cannot Create Method"))
.Method;
var property = typeof(T).GetProperty(propertyName) ?? throw new Exception("Couldn't Get the property");
var row = Expression.Parameter(typeof(T), "row");
Expression prop = Expression.Property(row, property);
// now making sure if the type is string
if (property.PropertyType != typeof(string))
{
//Here I want to cast it to string but the problem is exactly here anything I try feels like a dead end
prop = Expression.Call(prop, _tostring);
}
var func =
Expression.Lambda<Func<T, bool>>
(
Expression.Call
(
prop,
_compare,
Expression.Constant(filterValue)
),
row
);
return items.Where(func);
}
CodePudding user response:
I tried and tested it with some dummy objects; it seems to work.
I refined my answer to use ToString
var prop = Expression.Property(row, property);
Expression expression = prop;
if (prop.Type != typeof(string))
{
expression = Expression.Call(prop, "ToString", Type.EmptyTypes);
}
var func = Expression.Lambda<Func<T, bool>>
(
Expression.Call
(
expression,
_compare,
Expression.Constant(filterValue)
),
row
);
The above expression tree will be compiled to,
If the property type is not a string,
.Where(s => s.property.ToString().Contains("filter")))
If it's a string type,
.Where(s => s.property.Contains("filter")))