using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq.Expressions; using System.Reflection; namespace DataTable { /// /// Ускоренный обработчик свойства /// class PropertyHelper { delegate void SetterDelegate(object instanse, object[] values); delegate object GetterDelegate(object instanse); public string PropertyName { get; } public string PropertyDesctiption { get; } public Type PropertyType { get; } public string Id { get; } SetterDelegate Setter { get; } GetterDelegate Getter { get; } public PropertyHelper(PropertyInfo property) { PropertyName = property.Name; PropertyType = property.PropertyType; Id = MakeIdentity(property.PropertyType.Name, property.Name); PropertyDesctiption = GetDescription(property); 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(); } private string GetDescription(PropertyInfo property) { var descriptionAttr = property.GetCustomAttribute(); return descriptionAttr?.Description ?? string.Empty; } 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(); } }