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();
|
|||
|
}
|
|||
|
}
|