Automapper:如何利用自定义的INamingConvention? [英] Automapper: How to leverage a custom INamingConvention?

查看:208
本文介绍了Automapper:如何利用自定义的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆