EmitMapper и список - PullRequest
       38

EmitMapper и список

2 голосов
/ 05 марта 2012

Впервые я использую EmitMapper.У меня есть список объектов ex: Customer, и я хотел бы отобразить этот список в бесчисленном множестве CustomerDTO, как я могу это сделать?Tnx

Ответы [ 2 ]

2 голосов
/ 05 сентября 2012

Это просто, если у вас есть список и вы хотите преобразовать его в список DTO:

 var mapper = ObjectMapperManager.DefaultInstance.GetMapper<Customer, CustomerDTO>();

 IEnumerable<CustomerDTO> dtos = listOfCustomer.Select(mapper.map);

Преамбула - это когда список находится в другом объекте, например User и UserDTO:

 class User { 
    public List<Customer> Customers { get; set; }
 }

 class UserDTO {
    public IEnumerable<CustomerDTO> Customers { get; set; }
 }

Похоже, что EmitMapper не поддерживает преобразование из List в Enumerable. Способ поддержать это будет:

      var customerMapper = ObjectMapperManager
            .DefaultInstance.GetMapper<Customer, CustomerDTO>();
      var mapper = ObjectMapperManager.DefaultInstance
            .GetMapper<User, UserDTO>(
               new DefaultMapConfig()
                 .ConvertUsing<List<Customer>, IEnumerable<CustomerDTO>>(
                     a => a.Select(customerMapper.Map))
        );
0 голосов
/ 24 октября 2016

Это можно сделать, создав собственный класс, реализовав интерфейс "ICustomConverterProvider" и добавив ConvertGeneric к "DefaultMapConfig".

Глядя на исходный код EmitMapper, я нашел класс с именем "ArraysConverterProvider", который является стандартным конвертером по умолчанию из ICollections в Arrays.

Адаптация кода из этого класса для работы с коллекциями IEnumerable:

class GenericIEnumerableConverterProvider : ICustomConverterProvider
    {
      public CustomConverterDescriptor GetCustomConverterDescr(
            Type from,
            Type to,
            MapConfigBaseImpl mappingConfig)
        {
            var tFromTypeArgs = DefaultCustomConverterProvider.GetGenericArguments(from);
            var tToTypeArgs = DefaultCustomConverterProvider.GetGenericArguments(to);
            if (tFromTypeArgs == null || tToTypeArgs == null || tFromTypeArgs.Length != 1 || tToTypeArgs.Length != 1)
            {
                return null;
            }
            var tFrom = tFromTypeArgs[0];
            var tTo = tToTypeArgs[0];
            if (tFrom == tTo && (tFrom.IsValueType || mappingConfig.GetRootMappingOperation(tFrom, tTo).ShallowCopy))
           {
               return new CustomConverterDescriptor
                {
                    ConversionMethodName = "Convert",
                    ConverterImplementation = typeof(GenericIEnumerableConverter_OneTypes<>),
                    ConverterClassTypeArguments = new[] { tFrom }
                };
            }

            return new CustomConverterDescriptor
            {
                ConversionMethodName = "Convert",
                ConverterImplementation = typeof(GenericIEnumerableConverter_DifferentTypes<,>),
                ConverterClassTypeArguments = new[] { tFrom, tTo }
            }; 
        }
    }


class GenericIEnumerableConverter_DifferentTypes<TFrom, TTo> : ICustomConverter
    {
        private Func<TFrom, TTo> _converter;
        public IEnumerable<TTo> Convert(IEnumerable<TFrom> from, object state)
        {
            if (from == null)
            {
                return null;
            } 

            TTo[] result = new TTo[from.Count()];
            int idx = 0;
            foreach (var f in from)
            {
                result[idx++] = _converter(f);
            }

            return result;
        } 

        public void Initialize(Type from, Type to, MapConfigBaseImpl mappingConfig)
        {
            var staticConverters = mappingConfig.GetStaticConvertersManager() ?? StaticConvertersManager.DefaultInstance;

            var staticConverterMethod = staticConverters.GetStaticConverter(typeof(TFrom), typeof(TTo));

           if (staticConverterMethod != null)
            {
                _converter = (Func<TFrom, TTo>)Delegate.CreateDelegate(
                    typeof(Func<TFrom, TTo>),
                    null,
                    staticConverterMethod
                );
            }
            else
            {
                _subMapper = ObjectMapperManager.DefaultInstance.GetMapperImpl(typeof(TFrom), typeof(TTo), mappingConfig);

                _converter = ConverterBySubmapper;
            }
        } 

        ObjectsMapperBaseImpl _subMapper;

        private TTo ConverterBySubmapper(TFrom from)
        {
            return (TTo)_subMapper.Map(from);
        }
    }


class GenericIEnumerableConverter_OneTypes<T>
    {

        public IEnumerable<T> Convert(IEnumerable<T> from, object state)
        {
            if (from == null)
          {
                return null;
            }

            return from;
        }
    } 

Этот код является просто копией с минимумом адаптациинасколько это возможно и может быть применено к объектам со многими уровнями иерархии .

Вы можете использовать приведенный выше код со следующей командой:

new DefaultMapConfig().ConvertGeneric(
typeof(IEnumerable<>),
typeof(IEnumerable<>),
new GenericIEnumerableConverterProvider());

Это спасло мой деньи я надеюсь спасти твою тоже!хехехе

...