DD.WellWorkover.Cloud/ConsoleApp1/TableMapper.cs

96 lines
3.4 KiB
C#
Raw Normal View History

2021-04-07 18:01:56 +05:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace ConsoleApp1
{
// для работы с таблицами
public class TableMapper<T>
{
2021-05-19 15:50:09 +05:00
private readonly Dictionary<string, PropertyHelper> props;
2021-04-07 18:01:56 +05:00
public TableMapper()
{
var props = typeof(T).GetProperties();
this.props = new Dictionary<string, PropertyHelper>(props.Length);
foreach (var prop in props)
{
var helper = new PropertyHelper(prop);
this.props.Add(helper.Id, helper);
}
2021-04-23 10:21:25 +05:00
2021-04-07 18:01:56 +05:00
}
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++;
2021-04-23 10:21:25 +05:00
}
2021-04-07 18:01:56 +05:00
return updatesCount;
}
}
/// <summary>
/// Ускоренный обработчик свойства
/// </summary>
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> { Expression.Convert(Expression.ArrayIndex(argumentsExpression, Expression.Constant(0)), PropertyType) };
var callExpression = Expression.Call(Expression.Convert(instanceExpression, setter.ReflectedType), setter, argumentExpressions);
Setter = Expression.Lambda<SetterDelegate>(callExpression, instanceExpression, argumentsExpression).Compile();
callExpression = Expression.Call(Expression.Convert(instanceExpression, getter.ReflectedType), getter);
Getter = Expression.Lambda<GetterDelegate>(Expression.Convert(callExpression, typeof(object)), instanceExpression).Compile();
}
2021-04-23 10:21:25 +05:00
public string PropertyName { get; }
2021-04-07 18:01:56 +05:00
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();
}
}