Skip to content

Instantly share code, notes, and snippets.

@kkrico
Created August 14, 2020 18:33
Show Gist options
  • Save kkrico/fef3c6ea8c9d3f73d37d423120d86a7a to your computer and use it in GitHub Desktop.
Save kkrico/fef3c6ea8c9d3f73d37d423120d86a7a to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using GASC.Dados;
namespace GASC.Negocio.Util
{
public static class Mapeador
{
private static readonly ConcurrentDictionary<Type, PropertyInfo[]> CacheDictionary;
static Mapeador()
{
CacheDictionary = new ConcurrentDictionary<Type, PropertyInfo[]>();
}
private static PropertyInfo[] GetPropriedadesDoCache(Type type)
{
if (CacheDictionary.ContainsKey(type))
{
return CacheDictionary[type];
}
PropertyInfo[] propriedades = type.GetProperties();
CacheDictionary.TryAdd(type, propriedades);
return propriedades;
}
/// <summary>
/// Mapea Enumerable. Está com constraint para class
/// Refatorar para adicionar isto ao mapeador e ser recursivo
/// </summary>
/// <typeparam name="TOrigem"></typeparam>
/// <typeparam name="TDestino"></typeparam>
/// <param name="listaOrigem"></param>
/// <returns></returns>
public static IEnumerable<TDestino> MapearEnumerable<TOrigem, TDestino>(IEnumerable<TOrigem> listaOrigem)
where TDestino : class, new()
where TOrigem : class
{
return MapearEnumerable<TOrigem, TDestino>(listaOrigem, null);
}
public static IEnumerable<TDestino> MapearEnumerable<TOrigem, TDestino>(IEnumerable<TOrigem> listaOrigem,
Action<TDestino, TOrigem> customMapeador)
where TDestino : class, new()
where TOrigem : class
{
var resultado = new List<TDestino>();
foreach (TOrigem itemOrigem in listaOrigem)
{
TDestino tmp = MapearPara<TOrigem, TDestino>(itemOrigem);
customMapeador?.Invoke(tmp, itemOrigem);
resultado.Add(tmp);
}
return resultado;
}
/// <summary>
/// Mapea uma lista paginada para uma lista paginada de DTO
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TOrigem"></typeparam>
/// <param name="origem"></param>
/// <returns></returns>
public static ListaPaginada<T> MapearListaPaginadaParaDTO<T, TOrigem>(ListaPaginada<TOrigem> origem)
where T : class, new()
where TOrigem : class
{
ListaPaginada<T> destino = MapearPara<ListaPaginada<TOrigem>, ListaPaginada<T>>(origem);
foreach (TOrigem resultado in origem.Resultado)
{
T tmp = MapearPara<TOrigem, T>(resultado);
destino.Resultado.Add(tmp);
}
return destino;
}
public static TResultado MapearPara<TOrigem, TResultado>(TOrigem origem)
where TResultado : class, new()
where TOrigem : class
{
if (origem == null) return null;
PropertyInfo[] propriedadesOrigem = GetPropriedadesDoCache(typeof (TOrigem));
PropertyInfo[] propriedadesDestino = GetPropriedadesDoCache(typeof (TResultado));
var resultado = new TResultado();
foreach (PropertyInfo propDestino in propriedadesDestino)
{
//#if DEBUG
// var isMapeada = false;
//#endif
PropertyInfo propriedadeEncontradaNaOrigem =
propriedadesOrigem.FirstOrDefault(
p => string.Compare(p.Name, propDestino.Name, StringComparison.InvariantCultureIgnoreCase) == 0);
PropertyInfo propriedadeEncontradaNoDestino =
propriedadesDestino.FirstOrDefault(
p => string.Compare(p.Name, propDestino.Name, StringComparison.InvariantCultureIgnoreCase) == 0);
if (propriedadeEncontradaNoDestino != null && propriedadeEncontradaNaOrigem != null)
{
if (!propriedadeEncontradaNoDestino.CanWrite) continue;
if (propriedadeEncontradaNaOrigem.PropertyType.IsAssignableFrom(propDestino.PropertyType))
{
object valor = propriedadeEncontradaNaOrigem.GetValue(origem, null);
propDestino.SetValue(resultado, valor, null);
//#if DEBUG
// isMapeada = true;
//#endif
}
else if (propriedadeEncontradaNoDestino.PropertyType.IsGenericType &&
propriedadeEncontradaNoDestino.PropertyType.GetGenericTypeDefinition() ==
typeof (Nullable<>))
{
Type nullableType =
Nullable.GetUnderlyingType(propriedadeEncontradaNaOrigem.PropertyType) ??
propriedadeEncontradaNaOrigem.PropertyType;
if (nullableType == propriedadeEncontradaNaOrigem.PropertyType)
{
object valor = propriedadeEncontradaNaOrigem.GetValue(origem, null);
propDestino.SetValue(resultado, valor, null);
//#if DEBUG
// isMapeada = true;
//#endif
}
//#if DEBUG
// isMapeada = true;
//#endif
}
}
//#if DEBUG
// if (!isMapeada)
// Debug.WriteLine("ATENÇÃO: Propriedade {0} do tipo {1} não mapeada".ToUpperInvariant(), propDestino.Name, typeof(TResultado).Name);
//#endif
}
return resultado;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment