AutoMapper与ASP.NET MVC结合,一般会在Controller的Action中使用AutoMapper把前台传递过来的Presentation Model转换成相应的业务逻辑上的Entity Model.如果在Action中写AutoMapper.CreateMap<T1,T2>,这些代码未免与业务逻辑无多大关系,所以不应该写在Action中。我们可以利用ASP.NET MVC中的Filter这个特点,以过滤器的方式在执行Action中AutoMapper的转换前就完成配置。
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(); } }
作者:sundacheng1989 发表于2013-8-21 13:16:38 原文链接
阅读:60 评论:0 查看评论