Search code examples
c#asp.net-coreautomapperasp.net-core-webapi

Access automapper from other class library in .net core


I am using asp.net core 2.0. I have DataAccess project and 20 API service project in my solution. And this number increasing every day. I will use AutoMapper. But I don't want to add automapper from NuGet for all projects. So, I want to add to the only DataAccess solution and adding profiles to DataAccess solution. And I want to call from API project by writing "mapper.Map(originalObject)". We can add Automapper to API project by adding startup.cs. But my DataAccess project is a class library. So it hasn't got startup.cs. How can I do this and can I access automapper from service projects? (I don't want to add automapper from NuGet to API)


Solution

  • There may be many solutions to this problem, I suggest only two of them and these aproaches may also change depending on your choice and scenario. Whether your helper class knows all the types that will be mapped or other user libraries need to register their own POCO classes, whether you prefer creating a mapper... You may also want to cache mappers and return it if it requested again.

    Simple code samples are as follows

    class Foo
    {
         public string Name { get; set; }
    }
    
    class Bar
    {
        public string Name { get; set; }
    }
    
    static void Main(string[] args)
    {
        //First approach usage
        Bar _bar1 = MapperHelper.MapFrom<Bar>(new Foo() { Name = "bbbbb" });
    
        //Second approach usage
        IMyMapper _myMapper = MapperHelper.GetMapperFor<Foo, Bar>();
        Bar _bar2 = _myMapper.MapFrom<Bar>(new Foo() { Name = "aaaAAA" });
    
        //Third approach usage
        Bar _bar3 = MapperHelper.Map<Bar, Foo>(new Foo() { Name = "cccc" });
    }
    
    public interface IMyMapper
    {
        T MapFrom<T>(object entity);
    }
    
    class MyMapper : IMyMapper
    {
          IMapper mapper;
    
          public MyMapper(IMapper mapper)
          {
                this.mapper = mapper;
          }
    
          public T MapFrom<T>(object entity)
          {
               return mapper.Map<T>(entity);
          }
    }
    
    public static class MapperHelper
    {
         static IMapper staticMapper;
    
        static MapperHelper()
        {
             var config = new MapperConfiguration(cfg => {
             cfg.CreateMap<Foo, Bar>();
             });
    
            staticMapper = config.CreateMapper();
         }
    
         //First approach, create a mapper and use it from a static method
         public static T MapFrom<T>(object entity)
         {
               return staticMapper.Map<T>(entity);
         }
    
         //Second approach (if users need to use their own types which are not known by this project)
         //Create you own mapper interface ans return it
         public static IMyMapper GetMapperFor<TSource, TDestination>()
         {
                var config = new MapperConfiguration(cfg => {
                    cfg.CreateMap<TSource, TDestination>();
                });
    
                var _mapper = config.CreateMapper();
    
                return new MyMapper(_mapper);
         }
    
         //Third sample, create and use mapper inside a static helper method
         //This is for mapping foreign types that this project does not 
         //include (e.g POCO or model types in other projects)
         public static TDestination Map<TDestination, TSource>(TSource entity)
         {
             var config = new MapperConfiguration(cfg => {
                   cfg.CreateMap<TSource, TDestination>();
                });
    
                var _mapper = config.CreateMapper();
    
                return _mapper.Map<TDestination>(entity);
         }
     }
    

    First one creates the configuration for known types and uses this mapper. Second one creates a mapper and returns it in a wrapper class. Third one creates and uses a mapper for mapping operation and only returns the mapped object.

    Most people do not like static classes and methods since they cause strict unwanted dependencies, they can not be replaced easily. So, creating factory or utility classes, registering them to a dependency injection container and in jecting them where needed is preferred.