|
|
|
@ -124,16 +124,12 @@ public class DefaultObjectMapper : IObjectMapper, ITransientDependency
|
|
|
|
|
|
|
|
|
|
protected virtual TDestination? TryToMapCollection<TSource, TDestination>(IServiceScope serviceScope, TSource source, TDestination? destination)
|
|
|
|
|
{
|
|
|
|
|
if (!typeof(TSource).IsGenericType || typeof(TSource).GetGenericTypeDefinition() != typeof(ICollection<>) ||
|
|
|
|
|
!typeof(TDestination).IsGenericType || typeof(TDestination).GetGenericTypeDefinition() != typeof(ICollection<>))
|
|
|
|
|
if (!IsCollectionGenericType<TSource, TDestination>(out var sourceArgumentType, out var destinationArgumentType, out var definitionGenericType))
|
|
|
|
|
{
|
|
|
|
|
//skip, not a collection
|
|
|
|
|
return default;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var sourceGenericTypeDefinition = typeof(TSource).GenericTypeArguments[0];
|
|
|
|
|
var destinationGenericTypeDefinition = typeof(TDestination).GenericTypeArguments[0];
|
|
|
|
|
var mapperType = typeof(IObjectMapper<,>).MakeGenericType(sourceGenericTypeDefinition, destinationGenericTypeDefinition);
|
|
|
|
|
var mapperType = typeof(IObjectMapper<,>).MakeGenericType(sourceArgumentType, destinationArgumentType);
|
|
|
|
|
var specificMapper = serviceScope.ServiceProvider.GetService(mapperType);
|
|
|
|
|
if (specificMapper == null)
|
|
|
|
|
{
|
|
|
|
@ -148,17 +144,87 @@ public class DefaultObjectMapper : IObjectMapper, ITransientDependency
|
|
|
|
|
x.GetParameters().Length == (destination == null ? 1 : 2));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var result = Activator.CreateInstance(typeof(Collection<>).MakeGenericType(destinationGenericTypeDefinition))!.As<IList>();
|
|
|
|
|
foreach (var sourceItem in (IEnumerable)source!)
|
|
|
|
|
var sourceList = source!.As<IList>();
|
|
|
|
|
var result = definitionGenericType.IsGenericType
|
|
|
|
|
? Activator.CreateInstance(definitionGenericType.MakeGenericType(destinationArgumentType))!.As<IList>()
|
|
|
|
|
: Array.CreateInstance(destinationArgumentType, sourceList.Count);
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < sourceList.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
result.Add(destination == null
|
|
|
|
|
? method.Invoke(specificMapper, new [] { sourceItem })!
|
|
|
|
|
: method.Invoke(specificMapper, new [] { sourceItem, Activator.CreateInstance(destinationGenericTypeDefinition)! })!);
|
|
|
|
|
var invokeResult = destination == null
|
|
|
|
|
? method.Invoke(specificMapper, new [] { sourceList[i] })!
|
|
|
|
|
: method.Invoke(specificMapper, new [] { sourceList[i], Activator.CreateInstance(destinationArgumentType)! })!;
|
|
|
|
|
|
|
|
|
|
if (definitionGenericType.IsGenericType)
|
|
|
|
|
{
|
|
|
|
|
result.Add(invokeResult);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
result[i] = invokeResult;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (TDestination)result!;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual bool IsCollectionGenericType<TSource, TDestination>(out Type sourceArgumentType, out Type destinationArgumentType, out Type definitionGenericType)
|
|
|
|
|
{
|
|
|
|
|
sourceArgumentType = default!;
|
|
|
|
|
destinationArgumentType = default!;
|
|
|
|
|
definitionGenericType = default!;
|
|
|
|
|
|
|
|
|
|
if ((!typeof(TSource).IsGenericType && !typeof(TSource).IsArray) ||
|
|
|
|
|
(!typeof(TDestination).IsGenericType && !typeof(TDestination).IsArray))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var supportedCollectionTypes = new[]
|
|
|
|
|
{
|
|
|
|
|
typeof(IEnumerable<>),
|
|
|
|
|
typeof(ICollection<>),
|
|
|
|
|
typeof(Collection<>),
|
|
|
|
|
typeof(IList<>),
|
|
|
|
|
typeof(List<>)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (typeof(TSource).IsGenericType && supportedCollectionTypes.Any(x => x == typeof(TSource).GetGenericTypeDefinition()))
|
|
|
|
|
{
|
|
|
|
|
sourceArgumentType = typeof(TSource).GenericTypeArguments[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (typeof(TSource).IsArray)
|
|
|
|
|
{
|
|
|
|
|
sourceArgumentType = typeof(TSource).GetElementType()!;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sourceArgumentType == default!)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
definitionGenericType = typeof(List<>);
|
|
|
|
|
if (typeof(TDestination).IsGenericType && supportedCollectionTypes.Any(x => x == typeof(TDestination).GetGenericTypeDefinition()))
|
|
|
|
|
{
|
|
|
|
|
destinationArgumentType = typeof(TDestination).GenericTypeArguments[0];
|
|
|
|
|
|
|
|
|
|
if (typeof(TDestination).GetGenericTypeDefinition() == typeof(ICollection<>) ||
|
|
|
|
|
typeof(TDestination).GetGenericTypeDefinition() == typeof(Collection<>))
|
|
|
|
|
{
|
|
|
|
|
definitionGenericType = typeof(Collection<>);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (typeof(TDestination).IsArray)
|
|
|
|
|
{
|
|
|
|
|
destinationArgumentType = typeof(TDestination).GetElementType()!;
|
|
|
|
|
definitionGenericType = typeof(Array);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return destinationArgumentType != default!;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual TDestination AutoMap<TSource, TDestination>(object source)
|
|
|
|
|
{
|
|
|
|
|
return AutoObjectMappingProvider.Map<TSource, TDestination>(source);
|
|
|
|
|