2012-02-23 75 views
1

我正在设计一个数据库,设计师似乎很喜欢大写字母和下划线键。由于我有一个简单的ORM,我的数据模型也使用这些名称。我需要建立DTO,我宁愿给他们标准的名字,因为我们通过服务暴露他们。 下面的代码现在已更正!如果您需要使用多个命名约定Automapper:如何利用自定义的INamingConvention?

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

我有非常相似的问题,无法弄清楚。基本上想要将数据库生成的代码(例如customer_id)映射到CustomerId并且不起作用。您可以请发布您的完整代码进行此测试吗? thx – user1829319 2015-06-29 01:55:19

回答

1

在配置文件中创建的映射,并定义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"); 
} 

,如果你这样做了,并且不限定在两个配置文件相同的映射,我不认为你需要什么从原来的问题中“填补空白”,它应该已经设置为做正确的事情。

+0

您可能想抓取AutoMapper源代码并查看它,因为没有很多好的文档可用。特别是INamingConvention.cs中的2个INamingConvention的实现 – 2012-03-14 19:23:30

+0

好的,所以我听到的是你不能在特定的Map上设置命名约定,但是你可以在单独的配置文件中设置命名约定。所以上面的解决方案是创建两个单独的配置文件。让我试试看。是的,我已经很久以前阅读了源代码,但现在看起来我需要编写自己的INamingConvention。感谢您的提示 – nachonachoman 2012-03-15 22:56:57

+0

DotNet Zebra:根据您的建议,我试图重构并使用命名约定。我失败了。我使用可以运行的独立代码示例更新了上面的问题以证明问题。 – nachonachoman 2012-03-20 18:30:57

1

什么

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

是的,这是我要去的路线,但它当然会击败许多automapper的好处。我正在寻找一个属性命名约定,我可以将其应用于特定地图的粒度 – nachonachoman 2012-03-01 15:01:14

相关问题