0

Hello fellow overflowers,

I'm not sure if it is even possible or I'm fighting against the windmills but what I would like to accomplish is sort of generic mapper based on AutoMapper.

Using this mapper I would be able to specify some types to be mapped and both source and destination types will be the same.

Then I would like to provide a list of properties as a param to method which would specify a subset of all properties on particular type.

So calling a method would look like this:

Given following method signature

public T Map<TProp>(T source1, T source2, params Expression<Func<T,TProp>>[] propsToMap)

amm stands for AutoModelMapper.

amm.Map<>(
        adminFeeSource,
        adminFeeDestination,
        fee => fee.FeeAmount,
        fee => fee.NoValueMessage);

How to achieve that in safe way (using generics)? Is that even possible?

Kind regards

kamilwydrzycki
  • 451
  • 2
  • 6
  • 16

1 Answers1

0

I don't understand your question TBH since AFAIK you need to register your mappings for AutoMapper to work based on its documentation, but see if this will help you.

Use a static Mapper

public class MapperConfig
{
    public static MapperConfiguration MapperCfg { get; private set; }
    public static IMapper Mapper { get; private set; }

    public static void RegisterMappings()
    {
        MapperCfg = new MapperConfiguration(cfg =>
        {
            cfg.AllowNullCollections = true;
            cfg.AllowNullDestinationValues = true;

            #region Entity VMs

            cfg.CreateMap<Address, AddressVM>().MaxDepth(3).ReverseMap();
            cfg.CreateMap<ApplicationUserConfig, ApplicationUserConfigVM>().MaxDepth(3).ReverseMap();
            // ... You need to define the objects in the mapper config
            cfg.CreateMap<WarehouseConfig, WarehouseConfigVM>().MaxDepth(3).ReverseMap();

            #endregion
        });

        Mapper = MapperCfg.CreateMapper();
    }
}

On your application startup call MapperConfig.RegisterMappings(); to register the model mappings.

Then you can create an extension

public static class Extension
{
    public static IPagedList<TDestination> ToMappedPagedList<TSource, TDestination>(this IPagedList<TSource> list)
    {
        IMapper mapper = MapperConfig.Mapper;

        IEnumerable<TDestination> sourceList = mapper.Map<IEnumerable<TDestination>>(list);
        IPagedList<TDestination> pagedResult = new StaticPagedList<TDestination>(sourceList, list.GetMetaData());

        return pagedResult;
    }

    public static IEnumerable<TDestination> Map<TSource, TDestination>(this IEnumerable<TSource> list)
        where TSource : class
        where TDestination : class, new()
    {
        IMapper mapper = MapperConfig.Mapper;

        IEnumerable<TDestination> sourceList = mapper.Map<IEnumerable<TDestination>>(list);

        return sourceList;
    }

    public static TDestination Map<TSource, TDestination>(this TSource entity)
        where TSource : class
        where TDestination : class, new()
    {
        IMapper mapper = MapperConfig.Mapper;

        return mapper.Map<TDestination>(entity);
    }
}

Ideally you would register your IMapper in an IoC Container and not call MapperConfig.Mapper directly in your Extention.cs but this will do for the example.

Usage:

Address address = new Address();
AddressVM = address.Map<Address, AddressVM>();
jegtugado
  • 5,081
  • 1
  • 12
  • 35
  • Sure you have to register but I would like to make it in a sense dynamic. So let's say that I have some type T, and subset of properties for that type. Now what I would like to achieve is create generic method that would create and register that mapping based on parameters, so .. cfg.CreateMap() for all properties in that list. So I'm looking for something like cfg.Create().ForMembers(List). Hopefully it's more clear now. – kamilwydrzycki Jul 31 '18 at 09:26
  • @kamilw have you tried [Dynamic and Expando Objects Mapping](https://stackoverflow.com/a/7778398/6138713)? Your sample method signature seem to want to map two objects of the same type while allowing you to specify which property goes to which. It seems confusing and pointless specially if the source1 and source2 are really of the same type. – jegtugado Aug 01 '18 at 02:18