using ModuleTools.Attributes;
using System;
using System.Collections;
using System.Reflection;
namespace ModuleTools.BusinessLogics
{
///
/// Маппер сущностей
///
public class Mapper
{
///
/// Преобразование из одного класса в другой
///
///
///
///
///
///
public static To MapToClass(From obj, bool haveRigth) where To : class => FillObject(obj, (To)Activator.CreateInstance(typeof(To)), haveRigth);
///
/// Преобразование из одного класса в другой
///
///
///
///
///
///
public static To MapToClass(From obj, To newObject, bool haveRigth) where To : class => FillObject(obj, newObject, haveRigth);
///
/// Заполнение объекта
///
///
///
///
///
///
///
private static To FillObject(From obj, To newObject, bool haveRigth)
where To : class
{
if (obj == null)
{
return null;
}
if (newObject == null)
{
return null;
}
var typeFrom = typeof(From);
var typeTo = typeof(To);
var properties = typeTo.GetProperties();
foreach (var property in properties)
{
object value = obj;
var customAttribute = property.GetCustomAttribute();
if (customAttribute != null)
{
if (customAttribute.IsDifficle)
{
var props = customAttribute.PropertyNameFromModel.Split('.');
foreach (var prop in props)
{
if (prop == "ToString")
{
value = value.ToString();
break;
}
else if (prop == "Count")
{
value = (value as ICollection)?.Count;
break;
}
else if (prop == "Method")
{
int index = 0;
while (true)
{
if (props[index++] == "Method")
break;
if (index == props.Length)
{
break;
}
}
var methodName = props[index].Split('[')?[0];
if (string.IsNullOrEmpty(methodName))
{
break;
}
var parameters = props[index].Split(new char[] { '[' , ']'}, StringSplitOptions.RemoveEmptyEntries)?[1].Split(',');
var objs = new object[parameters.Length];
for(int i = 0; i < parameters.Length; ++i)
{
var type = parameters[i].Split(':')[0];
switch(type)
{
case "Enum":
objs[i] = (int)Enum.Parse(customAttribute.MethodParams[i], parameters[i].Split(':')[1]);
break;
}
}
value = typeFrom.InvokeMember(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, value, objs);
break;
}
var bindingProperty = value.GetType().GetProperty(prop);
if (bindingProperty != null)
{
value = bindingProperty.GetValue(value);
if (value is null)
{
break;
}
}
else
{
value = null;
break;
}
}
}
else
{
if (customAttribute.PropertyNameFromModel == "ToString")
{
value = value.ToString();
}
var bindingProperty = typeFrom.GetProperty(customAttribute.PropertyNameFromModel);
if (bindingProperty != null)
{
value = bindingProperty.GetValue(obj);
}
}
if ((haveRigth && !customAttribute.AllowCopyWithoutRigth) || customAttribute.AllowCopyWithoutRigth)
{
if (property.PropertyType.Name.StartsWith("Nullable"))
{
if (Nullable.GetUnderlyingType(property.PropertyType).IsEnum)
{
property.SetValue(newObject, Enum.Parse(Nullable.GetUnderlyingType(property.PropertyType), value.ToString()));
continue;
}
}
property.SetValue(newObject, value);
}
}
else
{
var bindingProperty = value.GetType().GetProperty(property.Name);
if (bindingProperty != null)
{
property.SetValue(newObject, bindingProperty.GetValue(value));
}
}
}
return newObject;
}
}
}