“CreateMap”语句应该放在哪里?

时间:2010-05-23 13:29:13

标签: asp.net-mvc automapper separation-of-concerns mvvm

我经常使用AutoMapper将模型(域)对象映射到ViewModel对象,然后由我的视图以模型/视图/视图模型模式使用。

这涉及许多'Mapper.CreateMap'语句,这些语句都必须执行,但只能在应用程序的生命周期中执行一次

从技术上讲,我应该将它们全部保存在某个静态方法中,从我的Application_Start()方法调用它(这是一个ASP.NET MVC应用程序)。

但是,在一个中心位置将许多不同的映射问题组合在一起似乎是错误的。

特别是当映射代码变得复杂并涉及格式化和其他逻辑时。

是否有更好的方法来组织映射代码,使其与所关注的ViewModel保持接近?

(我想出了一个想法 - 在每个ViewModel上有一个'CreateMappings'方法,在BaseViewModel中,在实例化时调用这个方法。但是,因为该方法只应该被调用一次在应用程序生命周期中,它需要一些额外的逻辑来缓存已调用CreateMappings方法的ViewModel类型列表,然后仅在必要时为不在该列表中的ViewModel调用它。)

3 个答案:

答案 0 :(得分:7)

如果你真的不想使用引导程序,那么至少一个静态构造函数是确保最多调用一次CreateMap的简单方法。 (与Jonathon的答案相比,没有更少的麻烦和更多的线程证明。)

public class AccountController : Controller 
{
    static AccountController()
    {
        Mapper.CreateMap<Models.User, ViewModels.UserProfile>();
        Mapper.CreateMap<Models.User, ViewModels.ChangePassword>();
    }
}

答案 1 :(得分:3)

如果使用配置文件,则可以将所有“CreateMap”调用放在那里。此外,您可以创建一个包含您的配置的静态引导程序类,并让启动部分只调用引导程序。

答案 2 :(得分:0)

好的,我现在这样做的方式是:

我在BaseController的构造函数中添加了一些逻辑,它运行'CreateMappings'方法,但每个Controller Type只运行一次:

public abstract class BaseController : Controller
{    
    public BaseController()
    {
        if (!controllersWithMappingsCreated.Contains(GetType()))
        {
            CreateMappings();
            controllersWithMappingsCreated.Enqueue(GetType());
        }
    }

    protected virtual void CreateMappings() { }
}

在每个具体的控制器中,我使用CreateMappings来声明与该控制器相关的所有Models / ViewModel的映射。

public class AccountController : BaseController
{
    public AccountController() : base() { }

    protected override void CreateMappings()
    { 
        Mapper.CreateMap<Models.User, ViewModels.UserProfile>();
        Mapper.CreateMap<Models.User, ViewModels.ChangePassword>();
    }
}

我还发现了一些涉及属性herehere的有趣替代方案,但是它们让我觉得有些过于复杂。