Automapper:如何利用自定义的INamingConvention



我正在使用一个数据库,在这个数据库中,设计师似乎真的很喜欢大写字母和下划线键。由于我有一个简单的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);
            }
        }
    }

在概要文件中创建映射,并根据需要定义INamingConvention参数。

我不喜欢全局/静态,所以我更喜欢使用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");
}

如果你这样做,并且没有在两个配置文件中定义相同的映射,我认为你不需要从最初的问题中"填补空白",它应该已经设置为做正确的事情。

怎么样

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

相关内容

  • 没有找到相关文章

最新更新