[英]AutoMapper Mapping one property to two properties by condition
有两个班
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;
}
}
}
I would like to map the ProductionDivision
property to one of properties of class B depending on the condition - null
(map to IsNullProductionDivision
) or not null
(map to ProductionDivisionValue
) of the source property value. 我可以像下面这样实现它。
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);
});
如果 {source property name} 的值为null
那么 IsNull{source property name} 的值为true
。 否则,如果 {source property name} 的值不是null
则 {source property name}Value 的值是 {source property name} 的值。
我有许多响应此映射规则的属性。 所以,我不想为上面的每个属性编写映射规则。 我想为这样的映射全局配置一个规则。
如何配置 AutoMapper 以便它可以处理如此复杂的映射?
我找到了解决方案。 解决方案非常简单明了。 结果如下:
完整代码:
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);
}
}
澄清:
添加(后/前)修复以将相应的属性添加到内部属性 map。 它需要在这里做,因为我们的属性应该被 AutoMapper 捕获。 否则属性将被放弃并且映射器配置将失败。
之后,我们配置这些属性需要如何映射。 我们调用ForAllPropertyMaps
方法,过滤所有属性并设置规则以映射适合我们过滤器的属性。 在创建映射器 object 时,将构建执行计划并查看指定的过滤器。
因此,根据源属性是否为 null 值,源属性将映射到不同的目标属性。 除此之外,如果不是必须调用的,则不会调用相应目标属性的相应 set 方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.