C# LINQ基于字符串数组[]选择列

C# LINQ基于字符串数组[]选择列,c#,linq,C#,Linq,我有一个方法可以生成查询并将其导出到excel。 我希望用户选择他们希望导出的列 我的问题和这篇文章有点类似 其中,我们可以在基于字符串[]列的列表中创建一个LINQ select查询,该查询应该类似于此_dbcontext.Person.select SelectorFunccolumns.SomeOtherQuery.ToList; 下面的查询和函数选择器Func列 附言: 我非常感谢您的启发,感谢您抽出时间。我认为这应该会有所帮助: 我从这里找到的 这是你的目标: public c

我有一个方法可以生成查询并将其导出到excel。 我希望用户选择他们希望导出的列

我的问题和这篇文章有点类似

其中,我们可以在基于字符串[]列的列表中创建一个LINQ select查询,该查询应该类似于此_dbcontext.Person.select SelectorFunccolumns.SomeOtherQuery.ToList; 下面的查询和函数选择器Func列

附言:
我非常感谢您的启发,感谢您抽出时间。

我认为这应该会有所帮助: 我从这里找到的

这是你的目标:

    public class Foo
{
    public string Property1 {get;set;}
    public string Property2 {get;set;}  
}
这是您的助手类:

  public static class ExpressionTreeHelper
{
    /// <summary> Returns an IEnumerable of anonymous type defined by <paramref name="properties"/>. </summary>
    public static IEnumerable<dynamic> SelectDynamic<T>(this IEnumerable<T> source, params string[] properties)
    {
        return SelectProperties<T>(source.AsQueryable(), properties).Cast<dynamic>();
    }

    private static IQueryable SelectProperties<T>(this IQueryable<T> queryable, IEnumerable<string> propertyNames)
    {
        // get propertyinfo's from original type
        var properties = typeof(T).GetProperties().Where(p => propertyNames.Contains(p.Name));

        // Create the x => expression
        var lambdaParameterExpression = Expression.Parameter(typeof(T));
        // Create the x.<propertyName>'s
        var propertyExpressions = properties.Select(p => Expression.Property(lambdaParameterExpression, p));

        // Creating anonymous type using dictionary of property name and property type
        var anonymousType = AnonymousTypeUtils.CreateType(properties.ToDictionary(p => p.Name, p => p.PropertyType));
        var anonymousTypeConstructor = anonymousType.GetConstructors().Single();
        var anonymousTypeMembers = anonymousType.GetProperties().Cast<MemberInfo>().ToArray();

        // Create the new {} expression using 
        var anonymousTypeNewExpression = Expression.New(anonymousTypeConstructor, propertyExpressions, anonymousTypeMembers);

        var selectLambdaMethod = GetExpressionLambdaMethod(lambdaParameterExpression.Type, anonymousType);
        var selectBodyLambdaParameters = new object[] { anonymousTypeNewExpression, new[] { lambdaParameterExpression } };
        var selectBodyLambdaExpression = (LambdaExpression)selectLambdaMethod.Invoke(null, selectBodyLambdaParameters);

        var selectMethod = GetQueryableSelectMethod(typeof(T), anonymousType);
        var selectedQueryable = selectMethod.Invoke(null, new object[] { queryable, selectBodyLambdaExpression }) as IQueryable;
        return selectedQueryable;
    }

    private static MethodInfo GetExpressionLambdaMethod(Type entityType, Type funcReturnType)
    { 
        var prototypeLambdaMethod = GetStaticMethod(() => Expression.Lambda<Func<object, object>>(default(Expression), default(IEnumerable<ParameterExpression>))); 
        var lambdaGenericMethodDefinition = prototypeLambdaMethod.GetGenericMethodDefinition(); 
        var funcType = typeof(Func<,>).MakeGenericType(entityType, funcReturnType); 
        var lambdaMethod = lambdaGenericMethodDefinition.MakeGenericMethod(funcType); 
        return lambdaMethod; 
    } 

    private static MethodInfo GetQueryableSelectMethod(Type entityType, Type returnType)
    { 
        var prototypeSelectMethod = GetStaticMethod(() => Queryable.Select(default(IQueryable<object>), default(Expression<Func<object, object>>))); 
        var selectGenericMethodDefinition = prototypeSelectMethod.GetGenericMethodDefinition();
        return selectGenericMethodDefinition.MakeGenericMethod(entityType, returnType);
    } 

    private static MethodInfo GetStaticMethod(Expression<Action> expression)
    { 
        var lambda = expression as LambdaExpression; 
        var methodCallExpression = lambda.Body as MethodCallExpression; 
        return methodCallExpression.Method; 
    } 
}

这是一个重复的问题,从这个OP

基于这些答案

public static Func<T, T> SelectorFunc<T>(string[] columns)
{

        // input parameter "o"
        var xParameter = Expression.Parameter(typeof(T), "o");

        // new statement "new Data()"
        var xNew = Expression.New(typeof(T));

        // create initializers
        var bindings = columns.Select(o => o.Trim())
            .Select(o =>
            {

                // property "Field1"
                var mi = typeof(T).GetProperty(o);

                // original value "o.Field1"
                var xOriginal = Expression.Property(xParameter, mi);

                // set value "Field1 = o.Field1"
                return Expression.Bind(mi, xOriginal);
            }
        );

        // initialization "new Data { Field1 = o.Field1, Field2 = o.Field2 }"
        var xInit = Expression.MemberInit(xNew, bindings);

        // expression "o => new Data { Field1 = o.Field1, Field2 = o.Field2 }"
        var lambda = Expression.Lambda<Func<T, T>>(xInit, xParameter);

        // compile to Func<Data, Data>
        return lambda.Compile();
}
使用该函数的将是_dbcontext.Person.SomeOtherQuery.Select SelectorFunccolumns.ToList


谢谢@Tấ谢谢你的回答

您的案例是动态选择的,此答案由、、分隔列字段,。所以您的字符串[]列将是字符串。Join,,colums通过comma@Tấ这正是我要找的!谢谢,我建议,在所选列的基础上生成动态SQL查询[选择语句或数据库视图]进行导出,然后通过EF/ADO.NET使用SQL查询,这将非常易于处理和维护。
  public static class ExpressionTreeHelper
{
    /// <summary> Returns an IEnumerable of anonymous type defined by <paramref name="properties"/>. </summary>
    public static IEnumerable<dynamic> SelectDynamic<T>(this IEnumerable<T> source, params string[] properties)
    {
        return SelectProperties<T>(source.AsQueryable(), properties).Cast<dynamic>();
    }

    private static IQueryable SelectProperties<T>(this IQueryable<T> queryable, IEnumerable<string> propertyNames)
    {
        // get propertyinfo's from original type
        var properties = typeof(T).GetProperties().Where(p => propertyNames.Contains(p.Name));

        // Create the x => expression
        var lambdaParameterExpression = Expression.Parameter(typeof(T));
        // Create the x.<propertyName>'s
        var propertyExpressions = properties.Select(p => Expression.Property(lambdaParameterExpression, p));

        // Creating anonymous type using dictionary of property name and property type
        var anonymousType = AnonymousTypeUtils.CreateType(properties.ToDictionary(p => p.Name, p => p.PropertyType));
        var anonymousTypeConstructor = anonymousType.GetConstructors().Single();
        var anonymousTypeMembers = anonymousType.GetProperties().Cast<MemberInfo>().ToArray();

        // Create the new {} expression using 
        var anonymousTypeNewExpression = Expression.New(anonymousTypeConstructor, propertyExpressions, anonymousTypeMembers);

        var selectLambdaMethod = GetExpressionLambdaMethod(lambdaParameterExpression.Type, anonymousType);
        var selectBodyLambdaParameters = new object[] { anonymousTypeNewExpression, new[] { lambdaParameterExpression } };
        var selectBodyLambdaExpression = (LambdaExpression)selectLambdaMethod.Invoke(null, selectBodyLambdaParameters);

        var selectMethod = GetQueryableSelectMethod(typeof(T), anonymousType);
        var selectedQueryable = selectMethod.Invoke(null, new object[] { queryable, selectBodyLambdaExpression }) as IQueryable;
        return selectedQueryable;
    }

    private static MethodInfo GetExpressionLambdaMethod(Type entityType, Type funcReturnType)
    { 
        var prototypeLambdaMethod = GetStaticMethod(() => Expression.Lambda<Func<object, object>>(default(Expression), default(IEnumerable<ParameterExpression>))); 
        var lambdaGenericMethodDefinition = prototypeLambdaMethod.GetGenericMethodDefinition(); 
        var funcType = typeof(Func<,>).MakeGenericType(entityType, funcReturnType); 
        var lambdaMethod = lambdaGenericMethodDefinition.MakeGenericMethod(funcType); 
        return lambdaMethod; 
    } 

    private static MethodInfo GetQueryableSelectMethod(Type entityType, Type returnType)
    { 
        var prototypeSelectMethod = GetStaticMethod(() => Queryable.Select(default(IQueryable<object>), default(Expression<Func<object, object>>))); 
        var selectGenericMethodDefinition = prototypeSelectMethod.GetGenericMethodDefinition();
        return selectGenericMethodDefinition.MakeGenericMethod(entityType, returnType);
    } 

    private static MethodInfo GetStaticMethod(Expression<Action> expression)
    { 
        var lambda = expression as LambdaExpression; 
        var methodCallExpression = lambda.Body as MethodCallExpression; 
        return methodCallExpression.Method; 
    } 
}
public static void Main()
{
    var list = new[] {new Foo { Property1 = "foo1" }, new Foo { Property1 = "foo2" }};

    var result = list.SelectDynamic(nameof(property).toString());

    result.Dump();
}
public static Func<T, T> SelectorFunc<T>(string[] columns)
{

        // input parameter "o"
        var xParameter = Expression.Parameter(typeof(T), "o");

        // new statement "new Data()"
        var xNew = Expression.New(typeof(T));

        // create initializers
        var bindings = columns.Select(o => o.Trim())
            .Select(o =>
            {

                // property "Field1"
                var mi = typeof(T).GetProperty(o);

                // original value "o.Field1"
                var xOriginal = Expression.Property(xParameter, mi);

                // set value "Field1 = o.Field1"
                return Expression.Bind(mi, xOriginal);
            }
        );

        // initialization "new Data { Field1 = o.Field1, Field2 = o.Field2 }"
        var xInit = Expression.MemberInit(xNew, bindings);

        // expression "o => new Data { Field1 = o.Field1, Field2 = o.Field2 }"
        var lambda = Expression.Lambda<Func<T, T>>(xInit, xParameter);

        // compile to Func<Data, Data>
        return lambda.Compile();
}