AutoMapper的配置方法

来源:互联网 发布:峨眉山旅游 知乎 编辑:程序博客网 时间:2024/09/15 12:30

AutoMapper与ASP.NET MVC结合,一般会在Controller的Action中使用AutoMapper把前台传递过来的Presentation Model转换成相应的业务逻辑上的Entity Model.如果在Action中写AutoMapper.CreateMap<T1,T2>,这些代码未免与业务逻辑无多大关系,所以不应该写在Action中。我们可以利用ASP.NET MVC中的Filter这个特点,以过滤器的方式在执行Action中AutoMapper的转换前就完成配置。


首先,要定义一个MyProfile, 继承自AutoMapper的Profile类,并且重写Configure()方法,在这个方法中进行配置。
public class OrderDomainMvcProfile : Profile    {        public override string ProfileName        {            get { return "OrderDomainMvcProfile"; }        }        protected override void Configure()        {            // Map……    Mapper.CreateMap<T1, T2>().ForMember(……);}}

然后再Filter中进行加载

[AttributeUsageAttribute(AttributeTargets.Class |AttributeTargets.Method, Inherited = false, AllowMultiple = false)]public class AutoMapperConfigurationActionFilterAttribute : FilterAttribute{    public AutoMapperConfigurationActionFilterAttribute(Type profileType)    {       Mapper.Configuration.AddProfileThreadSafe(Activator.CreateInstance(profileType) as Profile);    }}
最后把Filter应用到Controller的Action
[AutoMapperConfigurationActionFilter(typeof(OrderDomainMvcProfile))]public virtual ActionResult OrderGrid_Select(GridCommand command){ ……        }


这里介绍另外一种比较特别的方法。我希望在程序刚刚开始启动,即Application_Start的时候,就完成所有的配置,一劳永逸。如果ASP.NET MVC有多个Domain对应多个Area,那么在global.asax.cs中Application_Start中就要写很多配置AutoMapper的代码。这里我们使用反射,去寻找DLL中实现了IStartupTask的接口的方法,然后运行Excecute方法即可。

创建一个IStartupTask接口

public interface IStartupTask{    void Execute();}
实现这个接口
public class AutoMapperStartupTask : IStartupTask {        public void Execute()        {                       Create<User, UserModel>();            Create<Widget, WidgetModel>();            Create<WidgetDefinition, WidgetDefinitionModel>();            //Mapper.CreateMap<ModuleDefinition, ModuleDefinitionModel>()            //  .ForMember(m => m.AppId, o => o.MapFrom(e => e.App == null ? (int?)null : e.App.Id))            //  .ForMember(m => m.AppTitle, o => o.MapFrom(e => e.App == null ? null : e.App.Title));            //Mapper.CreateMap<ModuleDefinitionModel, ModuleDefinition>();        }        protected virtual void Create<T1, T2>()        {            Mapper.CreateMap<T1, T2>();            Mapper.CreateMap<T2, T1>();        } }

在Global.ascx中一次性引入所有的AutoMapper配置
protected void Application_Start(){     ……     ExecuteStartupTasks();}private void ExecuteStartupTasks(){            List<IStartupTask> startupTasks = new List<IStartupTask>();            Assembly asm = this.ExecutingAssembly;            // get path of executing (bin) folder from the current executing assembly            string codeBase = this.ExecutingAssembly.CodeBase;            UriBuilder uri = new UriBuilder(codeBase);            string path = Uri.UnescapeDataString(uri.Path);            string bin = Path.GetDirectoryName(path);            string[] assemblies = Directory.GetFiles(bin, "*.dll");            foreach (String file in assemblies)            {                try                {                    if (File.Exists(file))                    {                        // load the assembly                        asm = Assembly.LoadFrom(file);                        // get all types from the assembly that inherit IStartupTask                        var query = from t in asm.GetTypes()                                    where t.IsClass && t.GetInterface(typeof(IStartupTask).FullName) != null                                    select t;                        // add types to list of startup tasks                        foreach (Type type in query)                        {                            startupTasks.Add((IStartupTask)Activator.CreateInstance(type));                        }                    }                }                catch (Exception ex)                {                    Exceptions.LogException(ex);                }            }            // execute each startup task            foreach (IStartupTask task in startupTasks)            {                task.Execute();            }}