using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace ConsoleApp1 { // для работы с таблицами public class TableMapper { Dictionary props; public TableMapper() { var props = typeof(T).GetProperties(); this.props = new Dictionary(props.Length); foreach (var prop in props) { var helper = new PropertyHelper(prop); this.props.Add(helper.Id, helper); } } public int UpdateObjectFromTable(ref T obj, Table table, int rowIndex) { var updatesCount = 0; if (table.Rows.Count() <= rowIndex) return 0; var row = table.Rows.ElementAt(rowIndex); var headerIndex = 0; foreach (var header in table.Headers) { var headerId = PropertyHelper.MakeIdentity(header.PropertyType.Name, header.Name); if (props.ContainsKey(headerId)) { props[headerId].Set(obj, row.ElementAt(headerIndex)); updatesCount++; } headerIndex++; } return updatesCount; } } /// /// Ускоренный обработчик свойства /// class PropertyHelper { public PropertyHelper(PropertyInfo property) { PropertyName = property.Name; PropertyType = property.PropertyType; Id = MakeIdentity(property.PropertyType.Name, property.Name); var setter = property.SetMethod; var getter = property.GetMethod; var instanceExpression = Expression.Parameter(typeof(object), "instance"); var argumentsExpression = Expression.Parameter(typeof(object[]), "arguments"); var argumentExpressions = new List { Expression.Convert(Expression.ArrayIndex(argumentsExpression, Expression.Constant(0)), PropertyType) }; var callExpression = Expression.Call(Expression.Convert(instanceExpression, setter.ReflectedType), setter, argumentExpressions); Setter = Expression.Lambda(callExpression, instanceExpression, argumentsExpression).Compile(); callExpression = Expression.Call(Expression.Convert(instanceExpression, getter.ReflectedType), getter); Getter = Expression.Lambda(Expression.Convert(callExpression, typeof(object)), instanceExpression).Compile(); } public string PropertyName { get; } public Type PropertyType { get; } public string Id { get; } delegate void SetterDelegate(object instanse, object[] values); delegate object GetterDelegate(object instanse); SetterDelegate Setter { get; } GetterDelegate Getter { get; } void SetValues(object instance, params object[] values) => Setter(instance, values); public void Set(object instance, object value) => SetValues(instance, value); public object Get(object instance) => Getter(instance); public static string MakeIdentity(string propertyTypeName, string propertyName) => $"{propertyTypeName}_{propertyName}".ToLower(); } }