LINQ : Dynamic select

前端 未结 10 787
北荒
北荒 2020-11-22 05:26

Consider we have this class :

    public  class Data
{
    public string Field1 { get; set; }
    public string Field2 { get; set; }
    public string Field         


        
10条回答
  •  感动是毒
    2020-11-22 05:56

    I writing the method in following line for you can work with nested fields taking advantage of Nicholas Butler and Ali.

    You can use this method for dynamically creating to lambda for pass to select and also works for nested fields. You can also work with IQueryable cases.

        /// 
        /// Format1: "Field1"
        /// Format2: "Nested1.Field1"
        /// Format3: "Field1:Field1Alias"
        /// 
        public static Expression> DynamicSelectGenerator(params string[] Fields)
        {
            string[] EntityFields = Fields;
            if (Fields == null || Fields.Length == 0)
                // get Properties of the T
                EntityFields = typeof(T).GetProperties().Select(propertyInfo => propertyInfo.Name).ToArray();
    
            // input parameter "x"
            var xParameter = Expression.Parameter(typeof(T), "x");
    
            // new statement "new Data()"
            var xNew = Expression.New(typeof(TSelect));
    
            // create initializers
            var bindings = EntityFields
                .Select(x =>
                {
                    string[] xFieldAlias = x.Split(":");
                    string field = xFieldAlias[0];
    
                    string[] fieldSplit = field.Split(".");
                    if (fieldSplit.Length > 1)
                    {
                        // original value "x.Nested.Field1"
                        Expression exp = xParameter;
                        foreach (string item in fieldSplit)
                            exp = Expression.PropertyOrField(exp, item);
    
                        // property "Field1"
                        PropertyInfo member2 = null;
                        if (xFieldAlias.Length > 1)
                            member2 = typeof(TSelect).GetProperty(xFieldAlias[1]);
                        else
                            member2 = typeof(T).GetProperty(fieldSplit[fieldSplit.Length - 1]);
    
                        // set value "Field1 = x.Nested.Field1"
                        var res = Expression.Bind(member2, exp);
                        return res;
                    }
                    // property "Field1"
                    var mi = typeof(T).GetProperty(field);
                    PropertyInfo member;
                    if (xFieldAlias.Length > 1)
                        member = typeof(TSelect).GetProperty(xFieldAlias[1]);
                    else member = typeof(TSelect).GetProperty(field);
    
                    // original value "x.Field1"
                    var xOriginal = Expression.Property(xParameter, mi);
    
                    // set value "Field1 = x.Field1"
                    return Expression.Bind(member, xOriginal);
                }
            );
    
            // initialization "new Data { Field1 = x.Field1, Field2 = x.Field2 }"
            var xInit = Expression.MemberInit(xNew, bindings);
    
            // expression "x => new Data { Field1 = x.Field1, Field2 = x.Field2 }"
            var lambda = Expression.Lambda>(xInit, xParameter);
    
            return lambda;
        }
    

    Usage:

    var s = DynamicSelectGenerator(
                "Name:SalesTeamName",
                "Employee.FullName:SalesTeamExpert"
                );
    
    var res = _context.SalesTeam.Select(s);
    
    public class SalesTeam
    {
        public string Name {get; set; }
    
        public Guid EmployeeId { get; set; }
        public Employee Employee { get; set; }
    }
    public class SalesTeamSelect
    {
        public string SalesTeamName {get; set; }
        public string SalesTeamExpert {get; set; }
    }
    

提交回复
热议问题