using System; using System.Collections; using System.Linq; using System.Reflection; using ToolsModule.ManagmentSecurity; namespace ToolsModule.ManagmentMapping { /// /// Маппер сущностей /// 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, true); /// /// Заполнение объекта /// /// /// /// /// /// /// /// private static To FillObject(From obj, To newObject, bool haveRigth, bool exsistRecord = false) 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().Where(x => x.CanWrite); foreach (var property in properties) { if (property.Name == "Id" && exsistRecord) { continue; } var checkRight = property.GetCustomAttribute(); if (!haveRigth && checkRight != null) { continue; } object value = null; var customAttribute = property.GetCustomAttribute(); if (customAttribute != null) { if (!haveRigth && !customAttribute.AllowCopyWithoutRigth) { continue; } value = GetValueFromCustomAttribute(customAttribute, typeFrom, obj); } else { var bindingProperty = typeFrom.GetProperty(property.Name); if (bindingProperty != null) { value = bindingProperty.GetValue(obj); } } if (value is null) { continue; } if (property.PropertyType.Name.StartsWith("Nullable") && Nullable.GetUnderlyingType(property.PropertyType).IsEnum) { property.SetValue(newObject, Enum.Parse(Nullable.GetUnderlyingType(property.PropertyType), value.ToString())); continue; } property.SetValue(newObject, value); } return newObject; } private static object GetValueFromCustomAttribute(MapConfigurationAttribute customAttribute, Type typeFrom, object obj) { object value = obj; 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] = 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; } } return value; } } }