消除对UrlHelper的依赖?

时间:2012-08-27 17:22:36

标签: asp.net-mvc-3 castle-windsor automapper

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

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

我可以为此考虑三种解决方案,其中没有一种真正让我信服(没有特别的顺序):

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

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

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

  4. 我想两个单独的地图制作者会使最有意义的(根据上下文选择个人资料),但我不知道应该怎么做这样做,这是我的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);
            }
        }
    }
    

1 个答案:

答案 0 :(得分:1)

通过模拟在非Web请求上下文中传递给RequestContext的{​​{1}}来解决。