forked from ddrilling/AsbCloudServer
98 lines
3.5 KiB
C#
98 lines
3.5 KiB
C#
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();
|
||
}
|
||
}
|