Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Initialize AutoMapper Profiles in referenced project DLLs in ASP.Net webapp

Struggling a little on how to use automapper in my project class libraries (dlls). See my structure of my overall solution below.

The WebApp fires up, and in Global.asax App Start, the AutoMapper.Configure() method is called to add the mapping profiles. For now I am just adding the Services.AutoMapperViewModelProfile. But I need to somehow account for the profiles in each of the WebStoreAdapters (BigCommerce and Shopify in the example below). I was hoping not to add references to each WebStoreAdapter in WebApp, just for the sake of being able to add the profiles during the AutoMapperConfig. If I add another call to AutoMapper.Initialize in WebStoreFactory, it overrides the one in WebApp.

Is there another way that I am missing or totally off base here in some other way?

WebApp
     - AutoMapperConfig
        - AddProfile Services.AutoMapperViewModelProfile

   Services.dll         
      - AutoMapperViewModelProfile

   Scheduler.dll (uses HangFire to execute cron jobs to get data from shop carts. Its UI is accessed via the WebApp)

       WebStoreAdapter.dll
            -WebStoreFactory

               BigCommerceAdapter.dll
                   - AutoMapperBigCommerceDTOProfile

               ShopifyAdapter.dll
                   - AutoMapperShopifyDTOProfile

Initializing as called from Global.asax:

public static class AutoMapperConfiguration
{
    public static void Configure()
    {
        Mapper.Initialize(am =>
        {
            am.AddProfile<AutoMapperViewModelProfile>();
        });
    }    
}

Profile:

public class AutoMapperViewModelProfile : Profile
{
    public override string ProfileName
    {
        get { return this.GetType().ToString(); }
    }

    protected override void Configure()
    {
        CreateMap<InventoryContainerHeader, InventoryContainerLabelPrintZPLViewModel>()
                .ForMember(vm => vm.StatusDescription, opt => opt.MapFrom(entity => entity.InventoryContainerStatus.DisplayText))
                .ForMember(dest => dest.ContainerDetails, option => option.Ignore())
                ;
        ...
   }
}
like image 558
crichavin Avatar asked Dec 25 '22 03:12

crichavin


1 Answers

One way to do this is to use reflection to load up all profiles:

        var assembliesToScan = AppDomain.CurrentDomain.GetAssemblies();
        var allTypes = assembliesToScan.SelectMany(a => a.ExportedTypes).ToArray();

        var profiles =
            allTypes
                .Where(t => typeof(Profile).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo()))
                .Where(t => !t.GetTypeInfo().IsAbstract);

        Mapper.Initialize(cfg =>
        {
            foreach (var profile in profiles)
            {
                cfg.AddProfile(profile);
            }
        });

You don't directly reference any one Automapper profile, but just load all Profile's from the current AppDomain.

like image 86
Jimmy Bogard Avatar answered Feb 16 '23 02:02

Jimmy Bogard