我一直在使用Team Foundation Server 2018的API。我能够以List<IDictionary<string, object>>
的形式连接到API并检索工作项列表,但这种格式不是很有用。需要对数据进行一些按摩以使其更加可用且对环路友好。
举个例子,我想采用这种格式的数据并将其显示在数据网格中。我创建了一个简单的WPF应用程序,没有任何花边和口哨来解决这个问题。
此示例有一个名为data
的变量,该变量的创建类似于我的TFS系统中的数据。
在MainWindow.xaml
我创建的所有内容都是名为DataGrid
的DataGrid。在MainWindow.xaml.cs
我打算将List<WorkItem>
映射到此DataGrid。
MainWindow.xaml
<Window x:Class="AutoMapperExample.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Title="AutoMapper Example" Height="350" Width="525" ResizeMode="CanResizeWithGrip">
<Grid>
<DataGrid x:Name="DataGrid" />
</Grid>
</Window>
MainWindow.xaml.cs
namespace AutoMapperExample.Views {
using System.Collections.Generic;
using System.Windows;
using AutoMapper;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
var data = new List<IDictionary<string, object>> {
new Dictionary<string, object> {
{"System.Id", 1}, {"System.State", "Open"}, {"System.TeamProject", "Project1"}, {"System.Title", "First Work Item Title for Project 1"}
},
new Dictionary<string, object> {
{"System.Id", 2}, {"System.State", "Closed"}, {"System.TeamProject", "Project2"}, {"System.Title", "Work Item Title for Project 2"}
},
new Dictionary<string, object> {
{"System.Id", 3}, {"System.State", "Closed"}, {"System.TeamProject", "Project1"}, {"System.Title", "Second Work Item Title for Project 1"}
}
};
DataGrid.ItemsSource = ParseData(data);
}
private IEnumerable<WorkItem> ParseData(List<IDictionary<string, object>> data) {
Mapper.Initialize(cfg => {
// cfg.CreateMap<List<IDictionary<string,object>>, List<WorkItem>>();
// cfg.CreateMap<IDictionary<string, object>, WorkItem>();
// cfg.RecognizePrefixes("System.");
// cfg.ReplaceMemberName("System.", string.Empty);
});
var workItems = Mapper.Map<List<WorkItem>>(data);
return workItems;
}
}
public class WorkItem {
public int Id { get; set; }
public string Project { get; set; }
public string State { get; set; }
public string Title { get; set; }
}
}
请注意,所有词典的键也都以System.
为前缀。
我决定使用AutoMapper来解决这个问题,结果列表中包含正确数量的项目,但所有属性都是默认值或null。该示例已注释代码,该代码显示了我尝试过的内容,但它们都具有相同的结果。
AutoMapper是解决此问题的方法吗?如果是这样,我需要进行哪些调整才能正确转换为List<WorkItem>
答案 0 :(得分:1)
您可以通过中间序列化作弊。在模型上应用[JsonProperty]
属性:
public class WorkItem
{
[JsonProperty("System.Id")]
public int Id { get; set; }
[JsonProperty("System.TeamProject")]
public string Project { get; set; }
[JsonProperty("System.State")]
public string State { get; set; }
[JsonProperty("System.Title")]
public string Title { get; set; }
}
然后在后台使用Newtonsoft.Json
序列化程序实现自定义类型转换器:
public class WorkItemTypeConverter : ITypeConverter<IDictionary<string, object>, WorkItem>
{
public WorkItem Convert(IDictionary<string, object> source, WorkItem destination, ResolutionContext context)
{
var json = JsonConvert.SerializeObject(source);
return JsonConvert.DeserializeObject<WorkItem>(json);
}
}
并指定其在AutoMapper配置中的用法:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<IDictionary<string, object>, WorkItem>()
.ConvertUsing<WorkItemTypeConverter>();
});
我的答案基于Darin Dimitrov的this one。