1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Reflection;
- // ReSharper disable StaticMemberInGenericType
- namespace VCommon.VAutoMapper.Internals
- {
- internal static class MiddleMapper<TDto>
- {
- private static readonly Dictionary<Type, Type> MiddleClasses = new Dictionary<Type, Type>();
- private static readonly Dictionary<Type, Func<object, object>> MiddleProjection = new Dictionary<Type, Func<object, object>>();
- private static readonly Type DtoType = typeof(TDto);
- public static TDto[] ProjectionToArray<TEntity>(IQueryable<TEntity> queryable)
- {
- Func<object, object> mp;
- lock (MiddleClasses)
- {
- lock (MiddleProjection)
- {
- var entityType = typeof(TEntity);
- if (false == MiddleClasses.TryGetValue(entityType, out var mt))
- mt = MiddleClasses[entityType] = MiddleClass.Create(entityType, DtoType);
- if (false == MiddleProjection.TryGetValue(entityType, out mp))
- mp = MiddleProjection[entityType] = CreateMiddleProjection(entityType, mt);
- }
- }
- var arr = mp(queryable);
- var result = arr.MapTo<TDto[]>();
- return result;
- }
- private static Func<object, object> CreateMiddleProjection(Type entityType, Type mt)
- {
- // (object q) => ( (Queryable<[EntityType]>)q ).Projection<[mt]>().ToArray();
- var projectionArray = (typeof(VAutoMapper).GetMethod(nameof(VAutoMapper.ProjectionToArray), BindingFlags.Static | BindingFlags.Public) ?? throw new VAutoMapperException($"Missing method [{typeof(VAutoMapper).FullName}.{nameof(VAutoMapper.ProjectionToArray)}<>]?"))
- .MakeGenericMethod(entityType, mt);
- var p = Expression.Parameter(typeof(object));
- var unbox = Expression.Convert(p, typeof(IQueryable<>).MakeGenericType(entityType));
- var invoke = Expression.Call(null, projectionArray, unbox);
- var exp = Expression.Lambda<Func<object, object>>(invoke, p);
- return exp.Compile();
- }
- }
- }
|