Automapper: как использовать собственную INamingConvention? - PullRequest
2 голосов
/ 23 февраля 2012

Я работаю с базой данных, где дизайнеры действительно наслаждались заглавными буквами и ключом подчеркивания. Поскольку у меня есть простой ORM, мои модели данных также используют эти имена. Мне нужно создавать DTO, и я бы предпочел дать им стандартные имена, поскольку мы предоставляем их через сервисы. Код ниже теперь исправлен! Тест пройден, поэтому используйте его в качестве справочного материала, если вам нужно использовать несколько соглашений об именах 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); } } }

Ответы [ 2 ]

1 голос
/ 14 марта 2012

Создайте свои сопоставления в профилях и определите параметры INamingConvention соответствующим образом.

Мне не нравится global / static, поэтому я предпочитаю использовать Initialize и определять все мои сопоставления вместе. Это также имеет дополнительное преимущество, заключающееся в разрешении вызова AssertConfiguration ... что означает, что если я прервал отображение, я получу исключение при запуске, а не всякий раз, когда в моем коде используется проблемное отображение.

Mapper.Initialize(configuration =>
{
    configuration.CreateProfile("Profile1", CreateProfile1);
    configuration.CreateProfile("Profile2", CreateProfile2);
});
Mapper.AssertConfigurationIsValid();

в том же классе с этим методом инициализации:

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");
}

если вы делаете это таким образом и не определяете одно и то же отображение в обоих профилях, я не думаю, что вам нужно что-либо, чтобы «заполнить пробел» из исходного вопроса, это уже должно быть настроено для выполнения правильная вещь.

1 голос
/ 29 февраля 2012

А как же

public class DATAMODELProfile : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<DATAMODEL, DATAMODEL>();
        Mapper.CreateMap<DATAMODEL, SOMETHINGELSE>();
        Mapper.CreateMap<DATAMODEL, DataModelDto>()
            .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.ID))
            .ForMember(dest => dest.FirstName, opt => opt.MapFrom(src => src.FIRST_NAME))
            .ForMember(dest => dest.ChildDataModels, opt => opt.MapFrom(src => src.CHILD_DATAMODELS));
    }
}
...