将字典列表转换为类列表

时间:2018-01-24 19:15:50

标签: c# wpf list dictionary automapper

我一直在使用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>

1 个答案:

答案 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