I have a Kendo grid that has serverside filtering turned on. The field to filter by is passed as a string. For example, I want to filter by \"SampleId\". Now, I need to writ
I didn't think any of these answered actually how to do the getproperty so included my working code after further research. mymodelclass is the class of the entity/model used to MyFilteredData.
var srchItem1 = typeof(mymodelclass).GetProperty("Name");
var srchItem2 = typeof(mymodelclass).GetProperty("Description");
var srchItem3 = typeof(mymodelclass).GetProperty("LongDescription");
if (MySearchText != null && srchItem1 != null)
{
if (srchItem2 == null) { srchItem2 = srchItem1; }
if (srchItem3 == null) { srchItem3 = srchItem1; }
MyFilteredData = MyFilteredData.
Where(c => srchItem1.GetValue(c).ToString().ToLower().Contains(MySearchText.ToLower()) ||
srchItem2.GetValue(c).ToString().ToLower().Contains(MySearchText.ToLower()) ||
srchItem3.GetValue(c).ToString().ToLower().Contains(MySearchText.ToLower())
);
}
if you like expressions, you can use them to get the value of a property like so (taken from some helpers i have made in LinqPad so it might not be full code):
public static class Helper {
public static IEnumerable<T> Select<T>( this IEnumerable enumerable, string memberName ) {
IQueryable queryable = enumerable.AsQueryable();
LambdaExpression expression = PredicateFor( queryable.ElementType, memberName );
return CreateQuery( queryable, "Select", new[] { expression.ReturnType }, expression ).Cast<T>();
}
public static MemberExpression NestedPropertyOrField(this Expression expression, string nestedPropertyOrFieldName) {
MemberExpression e;
if (nestedPropertyOrFieldName.IndexOf('.') >= 0) {
var split = nestedPropertyOrFieldName.Split(new[] { '.' }, 2, StringSplitOptions.RemoveEmptyEntries);
if (split.Length > 0) {
e = Expression.PropertyOrField(expression, split[0]);
if (split.Length > 1) {
e = NestedPropertyOrField(e, split[1]);
}
} else {
throw new ArgumentException("'" + nestedPropertyOrFieldName + "' is not a member of type '" + expression.Type.AssemblyQualifiedName + "'");
}
} else {
e = Expression.PropertyOrField(expression, nestedPropertyOrFieldName);
}
return e;
}
private static IEnumerable CreateQuery( IEnumerable enumerable, string method, Type[] typeArguments, params Expression[] arguments ) {
IQueryable queryable = enumerable.AsQueryable();
Type[] typeArgs = new[] { queryable.ElementType }.Concat( typeArguments ?? new Type[ 0 ] ).ToArray();
Expression[] args = new[] { queryable.Expression }.Concat( arguments ?? new Expression[ 0 ] ).ToArray();
MethodCallExpression methodCallExpression = Expression.Call( typeof( Queryable ), method, typeArgs, args );
return queryable.Provider.CreateQuery( methodCallExpression );
}
internal static LambdaExpression PredicateFor( Type elementType, string memberName ) {
var pe = Expression.Parameter( elementType, "@item" );
Expression expression = pe;
if ( memberName.StartsWith( "@item", StringComparison.OrdinalIgnoreCase ) ) {
memberName = memberName.Substring( 5 );
}
if ( memberName.Length > 0 )
expression = NestedPropertyOrField( expression, memberName );
var delegateType = Expression.GetFuncType( elementType, expression.Type );
return Expression.Lambda( delegateType, expression, new[] {pe} );
}
}
and then do
string propertyName = // get property name from somewhere, ie: "SomeObject.NestedProperty.ID"
db.Cases.Select<string>(propertyName).Where(targetlist.Contains);
You can use an extension method and attach it to the class.
That method should use reflection to retrieve the property from the object.
Here are the pointers:
Once this is working, you'll want just to set and/or get the value of the property.
The GetProperty()
method above just returns the PropertyInfo
object.
To get or set the value you'll have to use the appropriate methods of PropertyInfo
.
I'd not expose the PropertyInfo
because it would ruin the magic.
Better have to extension methods, then:
T GetPropertyByName<T>(string name);
SetPropertyByName<T>(string name, T value);