web-dev-qa-db-ja.com

AutoMapper.Profileを使用してインスタンス(非静的)マッパーを作成する

次の回答で説明されているように、次の方法を使用して、マッパーのインスタンスを作成します。

var platformSpecificRegistry = AutoMapper.Internal.PlatformAdapter.Resolve<IPlatformSpecificMapperRegistry>();
platformSpecificRegistry.Initialize();

var autoMapperCfg = new AutoMapper.ConfigurationStore(new TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.Mappers);
var mappingEngine = new AutoMapper.MappingEngine(_autoMapperCfg);

次の質問で説明されているように:

AutoMapperコンテキストに応じてオブジェクトAをオブジェクトBに異なる方法でマップする方法

次のような Automapper profile クラスを使用して[再利用]してマッパーのインスタンスを作成するにはどうすればよいですか?

public class ApiTestClassToTestClassMappingProfile : Profile
{
    protected override void Configure()
    {
        base.Configure();
        Mapper.CreateMap<ApiTestClass, TestClass>()
            .IgnoreAllNonExisting();
    }
}

このような機能が必要な理由を説明するために、次のメソッドを使用して、すべてのAutomapperプロファイルクラスをIoCコンテナ[CastleWindsor]に登録します。

    IoC.WindsorContainer.Register(Types.FromThisAssembly()
                                       .BasedOn<Profile>()
                                       .WithServiceBase()
                                       .Configure(c => c.LifeStyle.Is(LifestyleType.Singleton)));

    var profiles = IoC.WindsorContainer.ResolveAll<Profile>();

    foreach (var profile in profiles)
    {
        Mapper.AddProfile(profile);
    }

    IoC.WindsorContainer.Register(Component.For<IMappingEngine>().Instance(Mapper.Engine));

上記は静的マッパークラスを初期化する必要性を完全に満たしていますが、[非静的マッパーを使用して]インスタンスマッパーを作成するためにオートマッパープロファイルクラスを再利用する方法がまったくわかりません。

5
MHOOS

プロファイルが正しいCreateMap呼び出しを呼び出すことを確認する必要があります。

public class ApiTestClassToTestClassMappingProfile : Profile
{ 
    protected override void Configure()
    {
        CreateMap<ApiTestClass, TestClass>()
            .IgnoreAllNonExisting();
    }
}

基本プロファイルクラスのCreateMapは、そのマップをそのプロファイルおよび構成に関連付けます。

また、IgnoreAllNonExistingは、CreateMap呼び出しのMemberList.Sourceオプションに置き換えられる必要があります。つまり、「宛先タイプの代わりに、検証するメンバーのリストとしてソースタイプを使用する」ということです。

5
Jimmy Bogard

これは、プロファイルを使用してMapperConfigurationを作成する方法です

public static class MappingProfile
{
    public static MapperConfiguration InitializeAutoMapper()
    {
        MapperConfiguration config = new MapperConfiguration(cfg =>
        {
            cfg.AddProfile(new WebMappingProfile());  //mapping between Web and Business layer objects
            cfg.AddProfile(new BLProfile());  // mapping between Business and DB layer objects
        });

        return config;
    }
}

プロファイルの例

//Profile number one saved in Web layer
public class WebMappingProfile : Profile
{
    public WebMappingProfile()
    {
        CreateMap<Question, QuestionModel>();
        CreateMap<QuestionModel, Question>();
        /*etc...*/
    }
}

//Profile number two save in Business layer
public class BLProfile: Profile
{
    public BLProfile()
    {
        CreateMap<BLModels.SubModels.Address, DataAccess.Models.EF.Address>();
        /*etc....*/
    }
}

オートマッパーをDIフレームワークに配線します(これはUnityです)

public static class UnityWebActivator
{
    /// <summary>Integrates Unity when the application starts.</summary>
    public static void Start()
    {
        var container = UnityConfig.GetConfiguredContainer();
        var mapper = MappingProfile.InitializeAutoMapper().CreateMapper();
        container.RegisterInstance<IMapper>(mapper);

        FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
        FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));

        DependencyResolver.SetResolver(new UnityDependencyResolver(container));

        // TODO: Uncomment if you want to use PerRequestLifetimeManager
        // Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
    }

    /// <summary>Disposes the Unity container when the application is shut down.</summary>
    public static void Shutdown()
    {
        var container = UnityConfig.GetConfiguredContainer();
        container.Dispose();
    }
}

マッピングにクラスでIMapperを使用する

public class BaseService
{
    protected IMapper _mapper;

    public BaseService(IMapper mapper)
    {
        _mapper = mapper;
    }

    public void AutoMapperDemo(){
        var questions = GetQuestions(token);
        return _mapper.Map<IEnumerable<Question>, IEnumerable<QuestionModel>>(questions);
    }

    public IEnumerable<Question> GetQuestions(token){
        /*logic to get Questions*/
    }
}

私の元の投稿はここにあります: http://www.codeproject.com/Articles/1129953/ASP-MVC-with-Automapper-Profiles

1
xszaboj

最終的に、マッパーインスタンスファクトリを次のように作成しました。

using AutoMapper;
using AutoMapper.Mappers;
using System.Collections.Generic;

public class MapperFactory<TSource,TDestination> where TSource : new() where TDestination : new()
{
    private readonly ConfigurationStore _config;

    public MapperFactory(IEnumerable<Profile> profiles)
    {
        var platformSpecificRegistry = AutoMapper.Internal.PlatformAdapter.Resolve<IPlatformSpecificMapperRegistry>();

        platformSpecificRegistry.Initialize();

        _config = new AutoMapper.ConfigurationStore(new TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.Mappers);

        foreach (var profile in profiles)
        {
            _config.AddProfile(profile);
        }
    }

    public TDestination Map(TSource sourceItem)
    {
        using (var mappingEngine = new MappingEngine(_config))
        {
            return mappingEngine.Map<TSource, TDestination>(sourceItem);
        }             
    }
}

そして今、私は私のソリューションで次のようなコードを持つことができます:

        var profiles = new Profile[]
        {
            new ApiTestClassToTestClassMappingProfile1(),
            new ApiTestClassToTestClassMappingProfile2(),
            new ApiTestClassToTestClassMappingProfile3() 
        };

        var mapper = new MapperFactory<ApiTestClass, TestClass>(profiles);

        var mappedItem = mapper.Map(testClassInstance);

上記のコードは、プロファイルクラスの再利用性を最大限に高めます。

0
MHOOS