1

現在、次のマッピングにAutoMapper依存しているプロファイルがあります。UrlHelper

CreateMap<Post, OpenGraphModel>().ForMember(
    m => m.Title,
    x => x.MapFrom(p => p.Link.Title)
).ForMember(
    m => m.Description,
    x => x.MapFrom(p => p.Link.Description)
).ForMember(
    m => m.Image,
    x => x.MapFrom(p => p.Link.Picture)
).ForMember(
    m => m.Url,
    x => x.MapFrom(p => urlHelper.RouteUrl("PostShortcut", new { id = p.Id }, "http"))
);

AutoMapperWeb リクエスト以外のコンテキストで自分のプロファイルを再利用するまでは、これで問題ありませんでした。

これには 3 つの解決策が考えられますが、どれも本当に納得できません (順不同)。

  1. UrlHelperマッピング プロファイルから依存関係を完全に削除します。
    これは、私の意見では、のUrlプロパティを手動でマッピングする必要があることを意味します。目的のオブジェクトに必要なすべてのプロパティを設定できるマッパーが気に入っています。OpenGraphModelAutoMapper

  2. いずれにせよ、非 Web 要求コンテキストはビュー モデルに直接マッピングされるべきではないため、非 Web コンテキストからこのマッピング プロファイルを削除します。
    これを実現するには、IMapperインスタンスをシングルトンではなく、Web リクエスト (またはスレッド) ごとに一時的に作成する必要があります。これにより、導入したくない追加のオーバーヘッドが発生します。

  3. 3 番目のオプションは、IMapperWeb 以外のリクエスト コンテキスト (つまり、ジョブ) で実装を使用しないことですが、マッパーを使用する必要があるコンポーネントを再利用しているため、これはほとんど問題外に思えます。

2 つのシングルトン マッパーを持つことが最も理にかなっていると思います(コンテキストに基づいてプロファイルを選択します)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using AutoMapper;
using AutoMapper.Mappers;
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;

namespace Common
{
    internal sealed class AutoMapperInstaller : IWindsorInstaller
    {
        private readonly Type[] profileTypes;

        public AutoMapperInstaller(params Type[] profileTypes)
        {
            if (profileTypes == null)
            {
                throw new ArgumentNullException("profileTypes");
            }
            this.profileTypes = profileTypes;
        }

        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            IEnumerable<Assembly> assemblies = profileTypes.Select(t => t.Assembly).ToList();

            foreach (Assembly assembly in assemblies)
            {
                container.Register(
                    AllTypes
                        .FromAssembly(assembly)
                        .BasedOn(typeof (ITypeConverter<,>))
                        .WithServiceSelf()
                    );
            }

            foreach (Assembly assembly in assemblies)
            {
                container.Register(
                    Classes
                        .FromAssembly(assembly)
                        .BasedOn<Profile>()
                        .LifestyleTransient()
                    );
            }

            container.Register(
                Component
                    .For<ITypeMapFactory>()
                    .ImplementedBy<TypeMapFactory>()
                    .LifestyleTransient()
                );

            container.Register(
                Component
                    .For<IConfiguration, IConfigurationProvider>()
                    .UsingFactoryMethod(InstanceConfigurationStore)
                    .LifestyleTransient()
                );

            container.Register(
                Component
                    .For<IMappingEngine>()
                    .ImplementedBy<MappingEngine>()
                    .LifestyleTransient()
                );

            container.Register(
                Component
                    .For<IMapper>()
                    .ImplementedBy<Mapper>()
                    .DynamicParameters(
                        (k, parameters) => parameters["profileTypes"] = profileTypes
                    )
                    .LifestyleSingleton()
                );
        }

        private ConfigurationStore InstanceConfigurationStore(IKernel kernel)
        {
            ITypeMapFactory typeMapFactory = kernel.Resolve<ITypeMapFactory>();
            IEnumerable<IObjectMapper> mappers = MapperRegistry.AllMappers();

            return new ConfigurationStore(typeMapFactory, mappers);
        }
    }
}
4

1 に答える 1

1

Web 以外のリクエスト コンテキストでRequestContext渡された をモックすることで解決しました。UrlHelper

于 2012-09-04T15:26:13.450 に答える