DD.WellWorkover.Cloud/ConsoleApp1/TableMapper.cs
2021-04-07 18:01:56 +05:00

98 lines
3.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
// для работы с таблицами
public class TableMapper<T>
{
Dictionary<string, PropertyHelper> props;
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);
}
}
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;
}
}
/// <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();
}
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();
}
}