11

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

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

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

但是,将许多不同的映射关注点集中在一个中心位置似乎是错误的。

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

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

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

4

3 回答 3

7

如果您真的不想使用引导程序,那么至少静态构造函数是一种确保最多调用一次 CreateMap 的简单方法。(与乔纳森的回答相比,更少的混乱和更多的线程证明。)

public class AccountController : Controller 
{
    static AccountController()
    {
        Mapper.CreateMap<Models.User, ViewModels.UserProfile>();
        Mapper.CreateMap<Models.User, ViewModels.ChangePassword>();
    }
}
于 2011-03-15T12:42:22.277 回答
3

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

于 2010-05-23T21:48:09.833 回答
0

好的,我目前的做法是这样的:

我在 BaseController 的构造函数中添加了一些逻辑,它运行“CreateMappings”方法,但每个控制器类型只运行一次:

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

    protected virtual void CreateMappings() { }
}

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

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

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

我还在这里这里找到了一些涉及 Attributes 的有趣替代方案,但是它们让我觉得有点过于复杂了。

于 2010-05-24T00:59:10.983 回答