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"))
);

这很好,直到我想AutoMapper在 Web 请求之外的上下文中重用我的个人资料。

我可以为此想到三个解决方案,但没有一个能真正说服我(没有特定的顺序):

  1. 从映射配置文件中完全删除UrlHelper依赖项。在我看来,
    这意味着我现在必须手动映射 的Url属性OpenGraphModel,这违背了使用的目的。AutoMapper我喜欢我的映射器能够在目标对象中设置我需要的所有属性。

  2. 从非 Web 上下文中删除此映射配置文件,因为非 Web 请求上下文不应该直接映射到视图模型。
    为了实现这一点,我必须让我的IMapper实例是瞬态的,每个 Web 请求(或线程),而不是单例,这会引入我不想引入的额外开销。

  3. 第三种选择是不在IMapper非 Web 请求上下文(即作业)上使用实现,但这似乎几乎不可能,因为我正在重用最终需要我使用映射器的组件。

我想拥有两个单例映射器将是最有意义的一个(根据上下文选择配置文件),但我不知道我应该如何做到这一点,这是我的 AutoMapper 安装程序的当前形式:

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 回答