Automapper:如何利用自定义的INamingConvention? [英] Automapper: How to leverage a custom INamingConvention?
问题描述
我正在使用一个数据库,设计师在其中似乎确实喜欢大写字母和下划线.由于我有一个简单的ORM,因此我的数据模型也使用这些名称.我需要构建DTO,并且我希望为它们指定标准名称,因为我们通过服务公开它们. 以下代码现已更正!测试通过,因此如果您需要使用多种命名约定,请以此为参考
I am working with a database where the designers really seemed to enjoy capital letters and the underscore key. Since I have a simple ORM, my data models use these names as well. I need to build DTOs and I would prefer to give them standard names since we are exposing them through services. The code below is now corrected! The test passes so use this as a reference if you need to use multiple naming conventions
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using AutoMapper;
using NUnit.Framework;
namespace AutomapperTest
{
public class DATAMODEL
{
public Guid ID { get; set; }
public string FIRST_NAME { get; set; }
public List<CHILD_DATAMODEL> CHILDREN { get; set; }
}
public class CHILD_DATAMODEL
{
public Guid ID { get; set; }
public int ORDER_ID { get; set; }
}
public class DataModelDto
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public List<ChildDataModelDto> Children { get; set; }
}
public class ChildDataModelDto
{
public Guid Id { get; set; }
public int OrderId { get; set; }
}
public class UpperUnderscoreNamingConvention : INamingConvention
{
private readonly Regex _splittingExpression = new Regex(@"[\p{Lu}0-9]+(?=_?)");
public Regex SplittingExpression { get { return _splittingExpression; } }
public string SeparatorCharacter { get { return "_"; } }
}
public class Profile1 : Profile
{
protected override void Configure()
{
SourceMemberNamingConvention = new UpperUnderscoreNamingConvention();
DestinationMemberNamingConvention = new PascalCaseNamingConvention();
CreateMap<DATAMODEL, DataModelDto>();
CreateMap<CHILD_DATAMODEL, ChildDataModelDto>();
}
}
[TestFixture]
public class Tests
{
[Test]
public void CanMap()
{
//tell automapper to use my convention
Mapper.Initialize(x => x.AddProfile<Profile1>());
//make a dummy source object
var src = new DATAMODEL();
src.ID = Guid.NewGuid();
src.FIRST_NAME = "foobar";
src.CHILDREN = new List<CHILD_DATAMODEL>
{
new CHILD_DATAMODEL()
{
ID = Guid.NewGuid(),
ORDER_ID = 999
}
};
//map to destination
var dest = Mapper.Map<DATAMODEL, DataModelDto>(src);
Assert.AreEqual(src.ID, dest.Id);
Assert.AreEqual(src.FIRST_NAME, dest.FirstName);
Assert.AreEqual(src.CHILDREN.Count, dest.Children.Count);
Assert.AreEqual(src.CHILDREN[0].ID, dest.Children[0].Id);
Assert.AreEqual(src.CHILDREN[0].ORDER_ID, dest.Children[0].OrderId);
}
}
}
推荐答案
在配置文件中创建映射,并适当地定义INamingConvention
参数.
Create your mappings in profiles, and define the INamingConvention
parameters as appropriate.
我不喜欢全局/静态,因此我更喜欢使用Initialize并一起定义所有映射.这还具有允许调用AssertConfiguration ...的额外好处.这意味着,如果我对映射感到厌烦,则在启动时会得到异常,而不是在我的代码开始使用有问题的映射时会得到异常.
I don't like the global/static, so I prefer using Initialize and define all of my mappings together. This also has the added benefit of allowing a call to AssertConfiguration... which means if I've borked my mapping I'll get the exception at launch instead of whenever my code gets around to using the problematic mapping.
Mapper.Initialize(configuration =>
{
configuration.CreateProfile("Profile1", CreateProfile1);
configuration.CreateProfile("Profile2", CreateProfile2);
});
Mapper.AssertConfigurationIsValid();
与该初始化方法位于同一类中:
in the same class with that initialization method:
public void CreateProfile1(IProfileExpression profile)
{
// this.CreateMap (not Mapper.CreateMap) statements that do the "normal" thing here
// equivalent to Mapper.CreateMap( ... ).WithProfile("Profile1");
}
public void CreateProfile2(IProfileExpression profile)
{
profile.SourceMemberNamingConvention = new PascalCaseNamingConvention();
profile.DestinationMemberNamingConvention = new LowerUnderscoreNamingConvention();
// this.CreateMap (not Mapper.CreateMap) statements that need your special conventions here
// equivalent to Mapper.CreateMap( ... ).WithProfile("Profile2");
}
如果您这样做,并且没有在两个配置文件中定义相同的映射,那么我认为您不需要任何东西来填充"原始问题,它应该已经被设置为可以正确的事情.
if you do it this way, and don't define the same mapping in both profiles, I don't think you need anything to "fill in the blank" from the original question, it should already be setup to do the right thing.
这篇关于Automapper:如何利用自定义的INamingConvention?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!