我有一个数据库表,它将XML数据块存储在字符串类型的字段中。我想将该 XML 的某些元素提取到自定义视图模型中。
在此示例中,ErrorTableModel.ErrorXML 保存示例 XML 字符串。我正在尝试从该字符串中获取"message"元素并将其映射到ErrorViewModel.message中。
使用自动映射器可以做到这一点吗?
示例字符串。此数据存储在 ErrorTableModel 的 ErrorXML 属性中:
<error
application="TestApp"
type="System.DivideByZeroException"
message="Something wicked this way comes."
</error>
数据库模型:
public class ErrorTableModel
{
public int ErrorId { get; set; }
public string ErrorXml { get; set; }
}
自定义视图模型:
public class ErrorViewModel
{
public int id { get; set; }
public string application { get; set; }
public string type { get; set; }
public string message { get; set; }
}
更新:我创建了一个新的帮助程序类,旨在帮助将 XML 分解。
protected override T ResolveCore(XElement source)
{
if (source == null || string.IsNullOrEmpty(source.Value))
{
return default(T);
}
return (T)Convert.ChangeType(source.Value, typeof(T));
}
当我从错误视图模型执行映射时,我正在尝试引用该方法。
Mapper.CreateMap<XElement, ErrorViewModel>()
.ForMember(
dest => dest.ErrorXml,
options => options.ResolveUsing<XElementResolver<string>>()
.FromMember(source => source.Element("error")
.Descendants("message").Single()));
可悲的是,这行不通...但我想我很接近。
更新2:
为澄清起见,我希望结果数据如下所示:
ErrorViewModel.application = "TestApp"
ErrorViewModel.type = "System.DivideByZeroException"
ErrorViewModel.message = "Something wicked this way comes."
像这样:
public class ErrorConverter1 : ITypeConverter<ErrorTableModel, ErrorViewModel>
{
public ErrorViewModel Convert(ResolutionContext context)
{
var dbModel = context.SourceValue as ErrorTableModel;
if (dbModel == null)
return null;
var xDocument = XDocument.Parse(dbModel.ErrorXml);
var errorElement = xDocument.Descendants(XName.Get("error")).Single();
return new ErrorViewModel()
{
id = dbModel.ErrorId,
application = errorElement.Attribute(XName.Get("application")).Value,
type = errorElement.Attribute(XName.Get("type")).Value,
message = errorElement.Attribute(XName.Get("message")).Value
};
}
}
或者通过 XML 反序列化。为此,您需要将ErrorViewModel
类更改为:
[XmlRoot("error")]
public class ErrorViewModel
{
public int id { get; set; }
[XmlAttribute("application")]
public string application { get; set; }
[XmlAttribute("type")]
public string type { get; set; }
[XmlAttribute("message")]
public string message { get; set; }
}
public class ErrorConverter2 : ITypeConverter<ErrorTableModel, ErrorViewModel>
{
public ErrorViewModel Convert(ResolutionContext context)
{
var dbModel = context.SourceValue as ErrorTableModel;
if (dbModel == null)
return null;
var serializer = new XmlSerializer(typeof(ErrorViewModel));
var result = (ErrorViewModel) serializer.Deserialize(new StringReader(dbModel.ErrorXml));
result.id = dbModel.ErrorId;
return result;
}
}
用法是这样的:
public class MappingProfile : Profile
{
protected override void Configure()
{
Mapper.CreateMap<ErrorTableModel, ErrorViewModel>()
.ConvertUsing<ErrorConverter1>()//or use the ErrorConverter2
;
}
}
class Program
{
static void Main(string[] args)
{
Mapper.Initialize(x => x.AddProfile<MappingProfile>());
var dbModel = new ErrorTableModel()
{
ErrorId = 1,
ErrorXml =
"<error application="TestApp" type="System.DivideByZeroException" message="Something wicked this way comes."></error>"
};
var viewModel = Mapper.Map<ErrorTableModel, ErrorViewModel>(dbModel);
Console.WriteLine(viewModel.id);
Console.WriteLine(viewModel.application);
Console.WriteLine(viewModel.type);
Console.WriteLine(viewModel.message);
}
}
根据需要添加保护子句。