考虑这个课程:
public class UglyXmlSoapObject {
public FIRST_NAMETYPESHAPE FIRST_NAMETYPESHAPE { get; set; }
public LAST_NAMETYPESHAPE LAST_NAMETYPESHAPE { get; set; }
public DEPT_TAX_CALCTYPESHAPE DEPT_TAX_CALCTYPESHAPE { get; set; }
}
public class FIRST_NAMETYPESHAPE {
public String Value { get; set; }
}
public class LAST_NAMETYPESHAPE {
public String Value { get; set; }
}
public class DEPT_TAX_CALCTYPESHAPE {
public Decimal Value { get; set; }
}
XXXX_XXXXXXTYPESHAPE只是公开String属性(Value)的包装器/持有者类。因此,要实际获取firstName,请调用:
String firstName = uglyXmlObject.FIRST_NAMETYPESHAPE.Value;
如何告诉Automapper始终尝试映射给定对象的.Value属性?我有几十个我想映射的Xml类,如下所示:
UglyXmlSource.FIRST_NAMETYPESHAPE.Value => poco.FirstName UglyXmlSource.LAST_NAMETYPESHAPE.Value => poco.LastName
我已经发现我需要一个自定义命名约定,但是,为了获得源成员Value,Automapper只调用ToString(),所以poco.FirstName的值最终为:“AutoMapperDemo.Program + FIRST_NAMETYPESHAPE”
也许IValueResolver可以做到这一点?我尝试使用ResolveUsing指定ValueResolver / IMemberValueResolver,但是不明白该怎么做。
我希望ValueResolver可以处理任何通用对象; UglyXmlSoapObject的成员只是通用对象,但成员始终具有Value属性。
public class SoapXmlNaming : INamingConvention
{
static CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
static TextInfo textInfo = cultureInfo.TextInfo;
public string SeparatorCharacter
{
get { return "_"; }
}
public Regex SplittingExpression { get; } = new Regex(@"[\p{Ll}\p{Lu}0-9]+(?=_?)");
public string ReplaceValue(Match match) =>
textInfo.ToTitleCase(match.Value);
}
public class Poco
{
public String FirstName { get; set; }
public String LastName { get; set; }
public Decimal DeptTaxCalc { get; set; }
}
我想出了答案。解决方案是使用自定义格式化程序来提取值,方法是注册使用ConvertUsing方法注册的Custom formatter(ITypeConvert的实现),如下所示:
public void Map(){
var config = new MapperConfiguration(cfg =>
cfg.CreateMap<Object, Object>().ConvertUsing<XmlPropertyConvert>();
cfg.CreateMap<UglyXmlSoapObject, Poco>();
}
public class XmlPropertyConverter : ITypeConverter<Object,Object>{
public object Convert(object source, object destination, ResolutionContext context) {
return GetValueObject(source)
}
private Object GetValueObject(Object member){
var type = member.GetType();
if (type.Name.ToLower().EndsWith("typeshape")){
var property = type.GetProperties().SingleOrDefault(x => x.Name == "Value");
if (property != null){
var value = property.GetValue(member);
return value;
}
}
return member;
}
}