using System.Collections; using System.Reflection; namespace Models.Helpers { public static class EntityMapper { public static TDestination MapEntity(TSource source) where TDestination : new() { var destination = new TDestination(); var sourceProps = typeof(TSource).GetProperties(); var destProps = typeof(TDestination).GetProperties(); foreach (var sourceProp in sourceProps) { var destProp = destProps.FirstOrDefault(p => p.Name == sourceProp.Name); if (destProp == null || !destProp.CanWrite) continue; var sourceValue = sourceProp.GetValue(source); if (sourceValue == null) { destProp.SetValue(destination, null); continue; } if (IsGenericCollection(destProp.PropertyType) && IsGenericCollection(sourceProp.PropertyType)) { var sourceElementType = sourceProp.PropertyType.GenericTypeArguments[0]; var destElementType = destProp.PropertyType.GenericTypeArguments[0]; var mappedList = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(destElementType))!; foreach (var item in (IEnumerable)sourceValue) { var mapMethod = typeof(EntityMapper) .GetMethod(nameof(MapEntity), BindingFlags.Public | BindingFlags.Static)! .MakeGenericMethod(sourceElementType, destElementType); var mappedItem = mapMethod.Invoke(null, new[] { item }); mappedList.Add(mappedItem); } destProp.SetValue(destination, mappedList); } else if (destProp.PropertyType.IsAssignableFrom(sourceProp.PropertyType)) { destProp.SetValue(destination, sourceValue); } } return destination; } private static bool IsGenericCollection(Type type) { if (!type.IsGenericType) return false; var genericDef = type.GetGenericTypeDefinition(); return typeof(IEnumerable<>).IsAssignableFrom(genericDef) || type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>)); } } }