我经常使用AutoMapper将模型(域)对象映射到ViewModel对象,然后由我的视图以模型/视图/视图模型模式使用。
这涉及许多'Mapper.CreateMap'语句,这些语句都必须执行,但只能在应用程序的生命周期中执行一次。
从技术上讲,我应该将它们全部保存在某个静态方法中,从我的Application_Start()方法调用它(这是一个ASP.NET MVC应用程序)。
但是,在一个中心位置将许多不同的映射问题组合在一起似乎是错误的。
特别是当映射代码变得复杂并涉及格式化和其他逻辑时。
是否有更好的方法来组织映射代码,使其与所关注的ViewModel保持接近?
(我想出了一个想法 - 在每个ViewModel上有一个'CreateMappings'方法,在BaseViewModel中,在实例化时调用这个方法。但是,因为该方法只应该被调用一次在应用程序生命周期中,它需要一些额外的逻辑来缓存已调用CreateMappings方法的ViewModel类型列表,然后仅在必要时为不在该列表中的ViewModel调用它。)
答案 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>();
}
}