AutoMapper按条件将一个属性映射到两个属性

问题描述 投票:0回答:1

有两个类别

        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(映射到null)或不将IsNullProductionDivision(映射到null)的条件将ProductionDivisionValue属性映射到B类属性之一值。我可以做到如下。

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,则{源属性名称} Value的值就是{源属性名称}的值。

我有许多属性可以响应此映射规则。因此,我不想为上述每个属性编写映射规则。我想在全球范围内配置此类映射的规则。

如何配置AutoMapper,使其可以处理这种复杂的映射?

c# automapper
1个回答
0
投票

我找到了解决方案。解决方案非常简单明了。结果如下:

完整代码:

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
        };
        var b = mapper.Map<B>(a);

        var c = new A()
        {
            ProductionDivision = "dsd"
        };
        var d = mapper.Map<B>(c);
    }
}

澄清

  1. 添加前缀和前置前缀可将相应的属性添加到内部属性映射中。如果我们不调用这些方法,则映射器映射器将无法验证属性映射,因为它将向内部属性映射中添加相应的属性
  2. 之后,我们配置如何映射这些属性。
    • 对于“值”属性我们添加条件以检查源属性不为null。如果为null,则将丢失映射。
    • 对于“ IsNull”属性,我们添加了一个从字符串类型到布尔类型的转换器。转换器只检查字符串源属性是否为空。如果为null,则转换器返回true,因此条件接收到true值并返回其值,并且映射将完成。否则,转换器返回false,因此条件也返回false,并且映射将丢失。

因此,根据源属性是否为空值,源属性将映射到不同的目标属性。

© www.soinside.com 2019 - 2024. All rights reserved.