LINQ to Entities - Addressing class properties with their string names

无人久伴 提交于 2019-12-01 14:04:54

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);

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);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!