AutoMapper Сопоставление одного свойства двум свойствам по условию - PullRequest
0 голосов
/ 04 ноября 2019

Существует два класса

        class A
        {
            public string ProductionDivision { get; set; }
        }


        class B
        {
            private object _productionDivision;

            public enum ProductionDivisionOneofCase
            {
                None = 0,
                IsNullproductionDivision = 15,
                ProductionDivisionValue = 16,
            }
            private ProductionDivisionOneofCase _productionDivisionCase = ProductionDivisionOneofCase.None;


            public bool IsNullProductionDivision
            {
                get { return _productionDivisionCase == ProductionDivisionOneofCase.IsNullproductionDivision ? (bool)_productionDivision : false; }
                set
                {
                    _productionDivision = value;
                    _productionDivisionCase = ProductionDivisionOneofCase.IsNullproductionDivision;
                }
            }

            public string ProductionDivisionValue
            {
                get { return _productionDivisionCase == ProductionDivisionOneofCase.ProductionDivisionValue ? (string)_productionDivision : ""; }
                set
                {
                    _productionDivision = value;
                    _productionDivisionCase = ProductionDivisionOneofCase.ProductionDivisionValue;
                }
            }
        }

Я хотел бы сопоставить свойство ProductionDivision с одним из свойств класса B в зависимости от условия - null (сопоставить с IsNullProductionDivision) или нетnull (соответствует ProductionDivisionValue) значения свойства источника. Я могу добиться этого, как показано ниже.

CreateMap<A, B>()
               .ForMember(g => g.IsNullProductionDivision, m =>
               {
                   m.PreCondition(s => s.ProductionDivision == null);
                   m.MapFrom(b => true);
               })
               .ForMember(g => g.ProductionDivisionValue, m =>
               {
                   m.PreCondition(s => s.ProductionDivision != null);
                   m.MapFrom(b => b.ProductionDivision);
               });

Если значение {имя свойства источника} равно null, то значение IsNull {имя свойства источника} равно true. Иначе, если значение {имя свойства источника} не равно null, тогда значение {имя свойства источника} Значение равно значению {имя свойства источника}.

У меня есть много свойств, которые отвечают этому правилу отображения,Поэтому я не хочу писать правила отображения для каждого свойства, как указано выше. Я хочу настроить правило для такого отображения глобально.

Как настроить AutoMapper, чтобы он мог обрабатывать такие сложные сопоставления?

1 Ответ

1 голос
/ 05 ноября 2019

Я нашел решение. Решение довольно простое и понятное. Получается следующим образом:

Полный код:

public class Program
{

    class A
    {
        public string ProductionDivision { get; set; }
    }


    class B
    {
        private object _productionDivision;

        public enum ProductionDivisionOneofCase
        {
            None = 0,
            IsNullproductionDivision = 15,
            ProductionDivisionValue = 16,
        }
        private ProductionDivisionOneofCase _productionDivisionCase = ProductionDivisionOneofCase.None;


        public bool IsNullProductionDivision
        {
            get { return _productionDivisionCase == ProductionDivisionOneofCase.IsNullproductionDivision ? (bool)_productionDivision : false; }
            set
            {
                _productionDivision = value;
                _productionDivisionCase = ProductionDivisionOneofCase.IsNullproductionDivision;
            }
        }

        public string ProductionDivisionValue
        {
            get { return _productionDivisionCase == ProductionDivisionOneofCase.ProductionDivisionValue ? (string)_productionDivision : ""; }
            set
            {
                _productionDivision = value;
                _productionDivisionCase = ProductionDivisionOneofCase.ProductionDivisionValue;
            }
        }
    }

   public class StrinToBoolCustomResolver
        : IValueConverter<string, bool>
    {
        public bool Convert(string sourceMember, ResolutionContext context)
        {
            return sourceMember == null;
        }
    }

    public class MyAutoMapperProfile
        : Profile
    {
        public MyAutoMapperProfile()
        {
            // add post and pre prefixes to add corresponding properties in the inner property map
            RecognizeDestinationPostfixes("Value");
            RecognizeDestinationPrefixes("IsNull");

            // add mapping for "value" property
            this.ForAllPropertyMaps(map => map.SourceMember.Name + "Value" == map.DestinationName,
                (map, expression) =>
                {
                    expression.Condition((source, dest, sMem, destMem) =>
                    {
                        return sMem != null;
                    });
                    expression.MapFrom(map.SourceMember.Name);
                });

            // add mapping for "IsNull" property
            this.ForAllPropertyMaps(map => "IsNull" + map.SourceMember.Name == map.DestinationName,
                (map, expression) =>
                {
                    expression.Condition((source, dest, sMem, destMem) =>
                    {
                        return (bool)sMem;
                    });
                    //expression.MapFrom(map.SourceMember.Name);
                    expression.ConvertUsing<string, bool>(new StrinToBoolCustomResolver(), map.SourceMember.Name);
                });



            CreateMap<A, B>();
               //.ForMember(g => g.IsNullProductionDivision, m =>
               //{
               //    m.PreCondition(s => s.ProductionDivision == null);
               //    m.MapFrom(b => true);
               //});
               //.ForMember(g => g.ProductionDivisionValue, m =>
               //{
               //    m.PreCondition(s => s.ProductionDivision != null);
               //    m.MapFrom(b => b.ProductionDivision);
               //});
        }
    }


    public static void Main(string[] args)
    {
        var configuration = new MapperConfiguration(cfg => {
            cfg.AddProfile(new MyAutoMapperProfile());
        });

        var mapper = new Mapper(configuration);
        mapper.ConfigurationProvider.AssertConfigurationIsValid();
        var a = new A()
        {
            ProductionDivision = null
        };
        // b._productionDivisionCase  will be equal IsNullproductionDivision 
        var b = mapper.Map<B>(a);

        var c = new A()
        {
            ProductionDivision = "dsd"
        };
        // d._productionDivisionCase  will be equal ProductionDivisionValue
        var d = mapper.Map<B>(c);
    }
}

Пояснение:

  1. добавьте (post / pre) исправления , чтобы добавить соответствующие свойства на внутреннюю карту свойств. Это нужно сделать здесь, потому что наши свойства должны отслеживаться AutoMapper. В противном случае свойства будут отменены, а конфигурация сопоставителя будет неудачной.

  2. После этого мы настраиваем, каким образом эти свойства должны отображаться. Мы вызываем метод ForAllPropertyMaps, фильтруя все свойства и устанавливая правило для сопоставления свойств, подходящих для нашего фильтра. При создании объекта сопоставления план выполнения будет построен с учетом указанных фильтров.

    • Для свойства "Значение" мы добавляем условие, чтобы проверить, является лисвойство источника не является нулевым. Если оно равно нулю, то сопоставление будет пропущено.
    • Для свойства "IsNull" Прежде всего, мы добавим конвертер для преобразования строкового типа в тип bool. Конвертер просто сравнивает свойство строки источника с нулевым значением. Если свойство источника равно нулю, то конвертер возвращает true. Итак, условие получает истинное значение, возвращает истину, и сопоставление будет выполнено. В противном случае преобразователь возвращает false, поэтому условие возвращает false и отображение будет пропущено.

Таким образом, сопоставление свойства источника будет происходить с различными свойствами назначения в зависимости от того, является ли свойство источника нулевым значением. Кроме того, соответствующие методы набора соответствующих свойств назначения не будут вызываться, если они не должны вызываться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...