AutoMapper如何全域性配置map條件過濾null值空值對所有對映起效

風靈使發表於2019-04-16

我們在使用Automapper的時候經常會遇到這樣的問題:假設展示給使用者的資料我們用UserDto類,User類就是我們的實體類。在給使用者編輯的時候,我們可能某些欄位在資料庫中為Null,這時候需要一些預設值 比如這裡UserDto中的BirTime,然後我們有一些人的習慣是在建構函式裡面進行賦值

  public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public  DateTime? BirTime{ get; set; }
    }

   public class UserDto
    {
         public UserDto()
        {
             this.BirTime=DateTime.Now;//把當前時間賦值給BirTime
        }
        public string Name { get; set; }
        public  DateTime? BirTime{ get; set; }
    }

 //假設我們從資料庫中取出來的值是這樣的,然後我們要和UserDto之間進行轉換
   User user = new User()
    {
        Id = 1,
        Name = "caoyc",
        BirTime=null
    };
  UserDto userDto=user.MapTo<UserDto>();//這裡把實體類轉換成前臺給使用者展示的UserDto類

看似這裡的程式碼都沒有什麼問題,但是我想在BirTimenull值的時候使用我UserDto類中的預設值 也就是當前時間,但在實際操作之後就會發現轉換過後的UserDto的值已經變掉了。那麼問題來了, 如何才能使用預設值呢。

方法有很多,比如

//第一種方法
UserDto userDto=user.MapTo<UserDto>();//這裡把實體類轉換成前臺給使用者展示的UserDto類
userDto.BirTime=userDto.BirTime==null?DateTime.Now:userDto.BirTime;

第一種方法就是在自己轉換完成之後判斷一下,然後重新賦值,用這種方法的話那寫建構函式自然就沒什麼必要了

//第二種方法
Mapper.CreateMap<User, UserDto>().ForAllMembers(opt => opt.Condition(srs => !srs.IsSourceValueNull));

第二種方法不怎麼好,當你需要轉換的類很多的時候,每個都要這樣寫,會很多也會很煩

//第三種方法,在全域性配置的時候加上這句話
private static void CreateMappingsInternal(IMapperConfigurationExpression cfg)
{
     //沒錯就是這句話
     cfg.ForAllMaps((a, b) => b.ForAllMembers(opt => opt.Condition((src, dest, sourceMember) => sourceMember != null)));
}

個人比較推薦第三種方法,不過這就相當於一棒子打死了,有利也有弊。


AutoMapper條件對映實戰

//有條件的物件拷貝
AutoMapper.Mapper.Initialize(cfg =>
                        {
                            cfg.CreateMap<OrderInfo, OrderInfo>()
                                .ForAllMembers(opts => opts.Condition((src, dest, srcMember, dMember) =>
                                srcMember != null && srcMember.ToString() != ""));
                        });

AutoMapper.Mapper.Map<OrderInfo, OrderInfo>(mainOrder, myorderinfo);


AutoMapper.Map忽略來自源物件中的所有空值的屬性

using AutoMapper;
using NUnit.Framework;

namespace Tests.UI
{
    [TestFixture]
    class AutomapperTests
    {

      public class Person
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public int? Foo { get; set; }
        }

        [Test]
        public void TestNullIgnore()
        {
            Mapper.CreateMap<Person, Person>()
                    .ForAllMembers(opt => opt.Condition(srs => !srs.IsSourceValueNull));

            var sourcePerson = new Person
            {
                FirstName = "Bill",
                LastName = "Gates",
                Foo = null
            };
            var destinationPerson = new Person
            {
                FirstName = "",
                LastName = "",
                Foo = 1
            };
            Mapper.Map(sourcePerson, destinationPerson);

            Assert.That(destinationPerson,Is.Not.Null);
            Assert.That(destinationPerson.Foo,Is.EqualTo(1));
        }
    }

相關文章