我在ASP中使用AutoMapper。NET MVC应用程序。有人告诉我,我应该把自动取款机移走。在其他地方创建地图,因为他们有很多开销。我不太确定如何设计我的应用程序,把这些调用放在一个地方。

我有一个网络层,服务层和数据层。每个项目都有自己的特色。我用Ninject来DI所有东西。我将在web层和服务层使用AutoMapper。

那么,你为AutoMapper的CreateMap设置了什么?你把它放在哪里?你怎么称呼它?


当前回答

没关系,只要它是一个静态类。这都是惯例。

我们的约定是,每个“层”(web、服务、数据)都有一个名为AutoMapperXConfiguration.cs的文件,带有一个名为Configure()的方法,其中X是层。

然后Configure()方法为每个区域调用私有方法。

下面是我们web层配置的一个例子:

public static class AutoMapperWebConfiguration
{
   public static void Configure()
   {
      ConfigureUserMapping();
      ConfigurePostMapping();
   }

   private static void ConfigureUserMapping()
   {
      Mapper.CreateMap<User,UserViewModel>();
   } 

   // ... etc
}

我们为每个“聚合”(User, Post)创建了一个方法,这样事情就被很好地分开了。

然后是Global.asax:

AutoMapperWebConfiguration.Configure();
AutoMapperServicesConfiguration.Configure();
AutoMapperDomainConfiguration.Configure();
// etc

它有点像“文字界面”——不能强制执行,但你希望它,所以你可以在必要时编码(和重构)。

编辑:

我只是想提一下我现在使用AutoMapper配置文件,所以上面的例子变成:

public static class AutoMapperWebConfiguration
{
   public static void Configure()
   {
      Mapper.Initialize(cfg =>
      {
        cfg.AddProfile(new UserProfile());
        cfg.AddProfile(new PostProfile());
      });
   }
}

public class UserProfile : Profile
{
    protected override void Configure()
    {
         Mapper.CreateMap<User,UserViewModel>();
    }
}

更干净/更坚固。

其他回答

对于使用AutoMapper新版本(5.x)的vb.net程序员。

Global.asax.vb:

Public Class MvcApplication
    Inherits System.Web.HttpApplication

    Protected Sub Application_Start()
        AutoMapperConfiguration.Configure()
    End Sub
End Class

AutoMapperConfiguration:

Imports AutoMapper

Module AutoMapperConfiguration
    Public MapperConfiguration As IMapper
    Public Sub Configure()
        Dim config = New MapperConfiguration(
            Sub(cfg)
                cfg.AddProfile(New UserProfile())
                cfg.AddProfile(New PostProfile())
            End Sub)
        MapperConfiguration = config.CreateMapper()
    End Sub
End Module

配置文件:

Public Class UserProfile
    Inherits AutoMapper.Profile
    Protected Overrides Sub Configure()
        Me.CreateMap(Of User, UserViewModel)()
    End Sub
End Class

映射:

Dim ViewUser = MapperConfiguration.Map(Of UserViewModel)(User)

将所有映射逻辑放在一个位置对我来说不是一个好的实践。因为映射类非常大,很难维护。

我建议把映射的东西和ViewModel类放在同一个cs文件中。您可以按照这个约定轻松地导航到您想要的映射定义。此外,在创建映射类时,您可以更快地引用ViewModel属性,因为它们在同一个文件中。

所以你的视图模型类看起来像这样:

public class UserViewModel
{
    public ObjectId Id { get; set; }

    public string Firstname { get; set; }

    public string Lastname { get; set; }

    public string Email { get; set; }

    public string Password { get; set; }
}

public class UserViewModelMapping : IBootStrapper // Whatever
{
    public void Start()
    {
        Mapper.CreateMap<User, UserViewModel>();
    }
}

没关系,只要它是一个静态类。这都是惯例。

我们的约定是,每个“层”(web、服务、数据)都有一个名为AutoMapperXConfiguration.cs的文件,带有一个名为Configure()的方法,其中X是层。

然后Configure()方法为每个区域调用私有方法。

下面是我们web层配置的一个例子:

public static class AutoMapperWebConfiguration
{
   public static void Configure()
   {
      ConfigureUserMapping();
      ConfigurePostMapping();
   }

   private static void ConfigureUserMapping()
   {
      Mapper.CreateMap<User,UserViewModel>();
   } 

   // ... etc
}

我们为每个“聚合”(User, Post)创建了一个方法,这样事情就被很好地分开了。

然后是Global.asax:

AutoMapperWebConfiguration.Configure();
AutoMapperServicesConfiguration.Configure();
AutoMapperDomainConfiguration.Configure();
// etc

它有点像“文字界面”——不能强制执行,但你希望它,所以你可以在必要时编码(和重构)。

编辑:

我只是想提一下我现在使用AutoMapper配置文件,所以上面的例子变成:

public static class AutoMapperWebConfiguration
{
   public static void Configure()
   {
      Mapper.Initialize(cfg =>
      {
        cfg.AddProfile(new UserProfile());
        cfg.AddProfile(new PostProfile());
      });
   }
}

public class UserProfile : Profile
{
    protected override void Configure()
    {
         Mapper.CreateMap<User,UserViewModel>();
    }
}

更干净/更坚固。

更新:这里发布的方法不再有效,因为SelfProfiler已被AutoMapper v2删除。

我会采取与Thoai类似的方法。但是我会使用内置的SelfProfiler<>类来处理映射,然后使用Mapper。SelfConfigure函数初始化。

使用该对象作为源:

public class User
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
    public string GetFullName()
    {
        return string.Format("{0} {1}", FirstName, LastName);
    }
}

这些是目的地:

public class UserViewModel
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class UserWithAgeViewModel
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public int Age { get; set; }
}

你可以创建这些配置文件:

public class UserViewModelProfile : SelfProfiler<User,UserViewModel>
{
    protected override void DescribeConfiguration(IMappingExpression<User, UserViewModel> map)
    {
    //This maps by convention, so no configuration needed
    }
}

public class UserWithAgeViewModelProfile : SelfProfiler<User, UserWithAgeViewModel>
{
    protected override void DescribeConfiguration(IMappingExpression<User, UserWithAgeViewModel> map)
    {
    //This map needs a little configuration
        map.ForMember(d => d.Age, o => o.MapFrom(s => DateTime.Now.Year - s.BirthDate.Year));
    }
}

要在应用程序中初始化,请创建这个类

 public class AutoMapperConfiguration
 {
      public static void Initialize()
      {
          Mapper.Initialize(x=>
          {
              x.SelfConfigure(typeof (UserViewModel).Assembly);
              // add assemblies as necessary
          });
      }
 }

将这一行添加到global.asax.cs文件中:

现在,您可以将映射类放在对您有意义的地方,而不必担心一个单一的映射类。

以上所有解决方案都提供了一个静态方法来调用(从app_start或任何位置),它应该调用其他方法来配置映射配置的部分。但是,如果您有一个模块化的应用程序,该模块可能在任何时候插入和退出应用程序,这些解决方案是行不通的。我建议使用WebActivator库,可以注册一些方法运行在app_pre_start和app_post_start的任何地方:

// in MyModule1.dll
public class InitMapInModule1 {
    static void Init() {
        Mapper.CreateMap<User, UserViewModel>();
        // other stuffs
    }
}
[assembly: PreApplicationStartMethod(typeof(InitMapInModule1), "Init")]

// in MyModule2.dll
public class InitMapInModule2 {
    static void Init() {
        Mapper.CreateMap<Blog, BlogViewModel>();
        // other stuffs
    }
}
[assembly: PreApplicationStartMethod(typeof(InitMapInModule2), "Init")]

// in MyModule3.dll
public class InitMapInModule3 {
    static void Init() {
        Mapper.CreateMap<Comment, CommentViewModel>();
        // other stuffs
    }
}
[assembly: PreApplicationStartMethod(typeof(InitMapInModule2), "Init")]

// and in other libraries...

你可以通过NuGet安装WebActivator。