ListHelper

using System;
using System.Reflection;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;

namespace xxxxxxxxxxxx
{
    public class ListHelper<T>
    {
        public List<T> CreateList(SqlDataReader reader)
        {
            Func<SqlDataReader, T> readRow = this.GetReader(reader);

            var results = new List<T>();

            while (reader.Read())
                results.Add(readRow(reader));

            return results;
        }
        public List<T> SortList(List<T> listToSort, string propertyName, bool ascending)
        {
            // verify that the propertyName is valid
            var propertyNames = typeof(T).GetProperties().ToList().Select(p => p.Name).ToList();
            if (!propertyNames.Contains(propertyName))
                throw new ArgumentOutOfRangeException("There is no property named: " + propertyName);

            var paramExpression = Expression.Parameter(typeof(T), "item");
            var propertyExpression = Expression.Convert(Expression.Property(paramExpression, propertyName), typeof(object));
            var lambdaExpression = Expression.Lambda<Func<T, object>>(propertyExpression, paramExpression);

            if (ascending)
                return listToSort.AsQueryable().OrderBy(lambdaExpression).ToList();
            else
                return listToSort.AsQueryable().OrderByDescending(lambdaExpression).ToList();
        }

        private Func<SqlDataReader, T> GetReader(SqlDataReader reader)
        {
            Delegate resDelegate;

            List<string> readerColumns = new List<string>();
            for (int index = 0; index < reader.FieldCount; index++)
                readerColumns.Add(reader.GetName(index));

            // a list of LINQ expressions that will be used for each data row
            var statements = new List<Expression>();

            // get the indexer property of SqlDataReader
            var indexerProperty = typeof(SqlDataReader).GetProperty("Item", new[] { typeof(string) });

            // Parameter expression to create instance of object
            ParameterExpression instanceParam = Expression.Variable(typeof(T));
            ParameterExpression readerParam = Expression.Parameter(typeof(SqlDataReader));

            // create and assign new instance of variable
            BinaryExpression createInstance = Expression.Assign(instanceParam, Expression.New(typeof(T)));
            statements.Add(createInstance);

            // loop through each of the properties in T to determine how to populate the new instance properties
            var properties = typeof(T).GetProperties();
            var columnNames = this.GetColumnNames(properties);

            foreach (var property in properties)
            {
                string columnName = columnNames[property.Name];
                //string columnName = property.Name;
                if (readerColumns.Contains(columnName))
                {
                    // get the instance.Property
                    MemberExpression setProperty = Expression.Property(instanceParam, property);

                    // the database column name will be what is in the columnNames list -- defaults to the property name
                    IndexExpression readValue = Expression.MakeIndex(readerParam, indexerProperty, new[] { Expression.Constant(columnName) });
                    ConstantExpression nullValue = Expression.Constant(DBNull.Value, typeof(System.DBNull));
                    BinaryExpression valueNotNull = Expression.NotEqual(readValue, nullValue);
                    if (property.PropertyType.Name.ToLower().Equals("string"))
                    {
                        ConditionalExpression assignProperty = Expression.IfThenElse(
                            valueNotNull,
                            Expression.Assign(setProperty, Expression.Convert(readValue, property.PropertyType)),
                            Expression.Assign(setProperty, Expression.Constant("", typeof(System.String)))
                        );
                        statements.Add(assignProperty);
                    }
                    else
                    {
                        ConditionalExpression assignProperty = Expression.IfThen(
                            valueNotNull,
                            Expression.Assign(setProperty, Expression.Convert(readValue, property.PropertyType))
                        );
                        statements.Add(assignProperty);
                    }
                }
            }
            var returnStatement = instanceParam;
            statements.Add(returnStatement);

            var body = Expression.Block(instanceParam.Type, new[] { instanceParam }, statements.ToArray());
            var lambda = Expression.Lambda<Func<SqlDataReader, T>>(body, readerParam);
            resDelegate = lambda.Compile();

            return (Func<SqlDataReader, T>)resDelegate;
        }
        private Dictionary<string, string> GetColumnNames(PropertyInfo[] properties)
        {
            var columnNames = new Dictionary<string, string>();
            foreach (var property in properties)
            {
                string columnName = property.Name;

                var attributes = property.GetCustomAttributes(typeof(Attributes.DatabaseProperty), true);
                if (attributes.Length > 0)
                    columnName = ((Attributes.DatabaseProperty)attributes[0]).ColumnName;

                columnNames.Add(property.Name, columnName);
            }
            return columnNames;
        }
    }
}

[AttributeUsage(AttributeTargets.Property)]
   public class DatabaseProperty : Attribute
   {
      private string _columnName;
      public string ColumnName
      {
         get { return _columnName; }
         set { _columnName = value; }
      }
   }

[Serializable]
    public class Employee
    {
        public int EmployeeID { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string Title { get; set; }
        public DateTime? BirthDate { get; set; }
        public DateTime? HireDate { get; set; }
        public string City { get; set; }
        public string Notes { get; set; }
        public byte[] Photo { get; set; }
    }

    [Serializable]
    public class Customer
    {
        public int CustomerID { get; set; }

        [DatabaseProperty(ColumnName = "CompanyName")]
        public string Name { get; set; }

        public string ContactName { get; set; }
        public string ContactTitle { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string Region { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }
        public string Phone { get; set; }
        public string Fax { get; set; }
    }

使用demo:

using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["northwind"].ConnectionString))
{
    conn.Open();
    var query = "select * from Employees order by LastName, FirstName";
    var cmd = new SqlCommand(query, conn);
    using (var reader = cmd.ExecuteReader())
    {
        this.EmployeeList = new GenericPopulator.ListHelper<Models.Employee>().CreateList(reader);
        this.EmployeeList = new GenericPopulator.ListHelper<Models.Employee>().SortList(this.EmployeeList, "LastName", true);

        rptEmployees.DataSource = this.EmployeeList;
        rptEmployees.DataBind();

        gvEmployees.DataSource = this.EmployeeList;
        gvEmployees.DataBind();
     
        reader.Close();
    }
    conn.Close();
}





你可能感兴趣的:(lambda,expression,assign,func,SqlDataReader)