我有一个已打开服务器端过滤的Kendo网格。要过滤的字段作为字符串传递。例如,我想过滤“SampleId”。现在,我需要编写一个LINQ to Entities查询,该查询可以使用强类型属性SampleId进行过滤。例如:
db.Cases.Where(x=>targetlist.Contains(x.SampleId))
其中targetlist是过滤器中的项目列表。
那么,实际上,有没有办法编写一个查询,以便“SampleId”可以直接转换为Case.SampleId?
我尝试过反射并使用了GetProperty和GetValue,LINQ to Entities不喜欢它。
任何建议都将不胜感激!
@zaitsman:这是在下面的评论中发布的代码,它是问题的实际解决方案,基于接受的答案。
public static class MyExtensions
{
public static string GetPropertyByName(this CaseV case1, string name)
{
var x = typeof (CaseV).GetProperty(name).GetValue(case1);
if (x != null)
{
return x.ToString();
} else {
return "none";
}
}
}
答案 0 :(得分:1)
我认为这些方法都没有真正回答如何进行getproperty,因此在进一步研究之后将我的工作代码包括在内。 mymodelclass是用于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())
);
}
答案 1 :(得分:0)
您可以使用扩展方法并将其附加到班级。
该方法应使用反射从对象中检索属性。
以下是指示:
一旦这个工作,你只需要设置和/或获取属性的值。
上面的GetProperty()
方法只返回PropertyInfo
对象。
要获取或设置值,您必须使用PropertyInfo
的适当方法。
我不会公开PropertyInfo
,因为它会毁掉魔法。
最好是扩展方法,然后:
T GetPropertyByName<T>(string name);
SetPropertyByName<T>(string name, T value);
答案 2 :(得分:0)
如果您喜欢表达式,可以使用它们来获取属性的值(取自我在LinqPad中创建的一些帮助程序,因此它可能不是完整代码):
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} );
}
}
然后再做
string propertyName = // get property name from somewhere, ie: "SomeObject.NestedProperty.ID"
db.Cases.Select<string>(propertyName).Where(targetlist.Contains);