首页 文章

LINQ to Entities - 使用字符串名称寻址类属性

提问于
浏览
0

我有一个Kendo网格,打开了服务器端过滤 . 要过滤的字段作为字符串传递 . 例如,我想过滤“SampleId” . 现在,我需要编写一个LINQ to Entities查询,该查询可以使用强类型属性SampleId进行过滤 . 例如:

db.Cases.Where(x=>targetlist.Contains(x.SampleId))

其中targetlist是过滤器中的项目列表 .

那么,实际上,有没有办法编写一个查询,以便“SampleId”可以直接转换为Case.SampleId?

我尝试过反射并使用了GetProperty和GetValue,LINQ to Entities不喜欢它 .

任何建议将不胜感激!


编辑(由原始海报srinaik2020的pid):

@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";
        }
    }
}

2 回答

  • 0

    您可以使用扩展方法并将其附加到类 .

    该方法应使用反射从对象中检索属性 .

    以下是指针:

    一旦这个工作,你只需要设置和/或获取属性的值 . 上面的 GetProperty() 方法只返回 PropertyInfo 对象 . 要获取或设置值,您必须使用 PropertyInfo 的相应方法 .

    我不会暴露 PropertyInfo 因为它会破坏魔法 .

    最好有扩展方法,然后:

    T GetPropertyByName<T>(string name);
    SetPropertyByName<T>(string name, T value);
    
  • 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);
    

相关问题