Sha*_*ean 213 asp.net-mvc configuration design-patterns automapper
我使用AutoMapper中的ASP.NET MVC应用程序.有人告诉我,我应该搬到AutoMapper.CreateMap其他地方,因为他们有很多开销.我不太确定如何设计我的应用程序将这些调用放在一个地方.
我有一个Web层,服务层和数据层.每个项目都有自己的.我用NinjectDI来做一切.我将AutoMapper在网络和服务层使用.
那么你AutoMapper的CreateMap 设置是什么?你把它放在哪里?你怎么称呼它?
RPM*_*984 218
没关系,只要它是一个静态类.这都是关于惯例的.
我们的惯例是每个"层"(Web,服务,数据)都有一个名为的文件,调用AutoMapperXConfiguration.cs一个方法Configure(),其中X是层.
Configure()然后该private方法为每个区域调用方法.
以下是我们的Web层配置示例:
public static class AutoMapperWebConfiguration
{
public static void Configure()
{
ConfigureUserMapping();
ConfigurePostMapping();
}
private static void ConfigureUserMapping()
{
Mapper.CreateMap<User,UserViewModel>();
}
// ... etc
}
Run Code Online (Sandbox Code Playgroud)
我们为每个"聚合"(用户,帖子)创建一个方法,因此事情很好地分开.
然后你的Global.asax:
AutoMapperWebConfiguration.Configure();
AutoMapperServicesConfiguration.Configure();
AutoMapperDomainConfiguration.Configure();
// etc
Run Code Online (Sandbox Code Playgroud)
它有点像"单词界面" - 不能强制执行它,但是你期望它,所以你可以在必要时编码(和重构).
编辑:
我想我现在提到我现在使用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>();
}
}
Run Code Online (Sandbox Code Playgroud)
更清洁/更强大.
Bre*_*red 33
只要您的Web项目引用它所在的程序集,您就可以将其放在任何位置.在您的情况下,我会将其放在服务层中,因为Web层和服务层可以访问它,如果您决定做一个控制台应用程序或者您正在进行单元测试项目,也可以从这些项目中获得映射配置.
在Global.asax中,您将调用设置所有地图的方法.见下文:
文件AutoMapperBootStrapper.cs
public static class AutoMapperBootStrapper
{
public static void BootStrap()
{
AutoMapper.CreateMap<Object1, Object2>();
// So on...
}
}
Run Code Online (Sandbox Code Playgroud)
应用程序启动时的Global.asax
只是打电话
AutoMapperBootStrapper.BootStrap();
Run Code Online (Sandbox Code Playgroud)
现在有些人会反对这种方法违反一些SOLID原则,他们有一些有效的论据.在这里他们是为了阅读.
在Bootstrapper中配置Automapper违反了开放封闭原则?
cod*_*ion 16
更新:此处发布的方法不再有效,因为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);
}
}
Run Code Online (Sandbox Code Playgroud)
这些作为目的地:
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; }
}
Run Code Online (Sandbox Code Playgroud)
您可以创建这些配置文件:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
要在应用程序中初始化,请创建此类
public class AutoMapperConfiguration
{
public static void Initialize()
{
Mapper.Initialize(x=>
{
x.SelfConfigure(typeof (UserViewModel).Assembly);
// add assemblies as necessary
});
}
}
Run Code Online (Sandbox Code Playgroud)
将此行添加到global.asax.cs文件中: AutoMapperConfiguration.Initialize()
现在,您可以将映射类放在对您有意义的位置,而不必担心单个映射类.
Mar*_*ius 15
对于那些坚持以下内容的人:
我在配置文件和利用我的ioc容器之间进行了组合:
IoC配置:
public class Automapper : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly().BasedOn<Profile>().WithServiceBase());
container.Register(Component.For<IMappingEngine>().UsingFactoryMethod(k =>
{
Profile[] profiles = k.ResolveAll<Profile>();
Mapper.Initialize(cfg =>
{
foreach (var profile in profiles)
{
cfg.AddProfile(profile);
}
});
profiles.ForEach(k.ReleaseComponent);
return Mapper.Engine;
}));
}
}
Run Code Online (Sandbox Code Playgroud)
配置示例:
public class TagStatusViewModelMappings : Profile
{
protected override void Configure()
{
Mapper.CreateMap<Service.Contracts.TagStatusViewModel, TagStatusViewModel>();
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
public class TagStatusController : ApiController
{
private readonly IFooService _service;
private readonly IMappingEngine _mapper;
public TagStatusController(IFooService service, IMappingEngine mapper)
{
_service = service;
_mapper = mapper;
}
[Route("")]
public HttpResponseMessage Get()
{
var response = _service.GetTagStatus();
return Request.CreateResponse(HttpStatusCode.Accepted, _mapper.Map<List<ViewModels.TagStatusViewModel>>(response));
}
}
Run Code Online (Sandbox Code Playgroud)
权衡是您必须通过IMappingEngine接口而不是静态Mapper引用Mapper,但这是我可以使用的惯例.
jav*_*iry 14
以上所有解决方案都提供了一种静态方法来调用(来自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...
Run Code Online (Sandbox Code Playgroud)
您可以WebActivator通过NuGet 安装.
Mah*_*vej 10
除了最好的答案,一个好方法是使用Autofac IoC liberary添加一些自动化.有了这个,您只需定义您的配置文件,无论启动如何.
public static class MapperConfig
{
internal static void Configure()
{
var myAssembly = Assembly.GetExecutingAssembly();
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(myAssembly)
.Where(t => t.IsSubclassOf(typeof(Profile))).As<Profile>();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var profiles = container.Resolve<IEnumerable<Profile>>();
foreach (var profile in profiles)
{
Mapper.Initialize(cfg =>
{
cfg.AddProfile(profile);
});
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
并在Application_Start方法中调用此行:
MapperConfig.Configure();
Run Code Online (Sandbox Code Playgroud)
上面的代码找到所有Profile子类并自动启动它们.
将所有映射逻辑放在一个位置对我来说不是一个好习惯.因为映射类非常大并且很难维护.
我建议将映射内容与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>();
}
}
Run Code Online (Sandbox Code Playgroud)
从新版本的AutoMapper使用静态方法不推荐使用Mapper.Map().因此,您可以将MapperConfiguration作为静态属性添加到MvcApplication(Global.asax.cs)并使用它来创建Mapper的实例.
App_Start
public class MapperConfig
{
public static MapperConfiguration MapperConfiguration()
{
return new MapperConfiguration(_ =>
{
_.AddProfile(new FileProfile());
_.AddProfile(new ChartProfile());
});
}
}
Run Code Online (Sandbox Code Playgroud)
的Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
internal static MapperConfiguration MapperConfiguration { get; private set; }
protected void Application_Start()
{
MapperConfiguration = MapperConfig.MapperConfiguration();
...
}
}
Run Code Online (Sandbox Code Playgroud)
BaseController.cs
public class BaseController : Controller
{
//
// GET: /Base/
private IMapper _mapper = null;
protected IMapper Mapper
{
get
{
if (_mapper == null) _mapper = MvcApplication.MapperConfiguration.CreateMapper();
return _mapper;
}
}
}
Run Code Online (Sandbox Code Playgroud)
https://github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API
| 归档时间: |
|
| 查看次数: |
89004 次 |
| 最近记录: |