Могу ли я создавать хорошо типизированные словари из данных XML, когда словари имеют разные типы? - PullRequest
0 голосов
/ 06 февраля 2020

Я хочу преобразовать следующую XML информацию в коллекцию словарей. Каждый <Transform> описывает словарь, а каждый <Map> описывает пару ключ-значение. Он предназначен для десериализации во время выполнения, поэтому решения, которые затрудняют сериализацию, не исключены.

<Config>
  <Transform Input="System.String" Output="System.Boolean">
    <Map Input="Yes" Output="true"></Map>
    <Map Input="No" Output="false"></Map>
  </Transform>
  <Transform Input="System.String" Output="System.Int32">
    <Map Input="Category1" Output="1"></Map>
    <Map Input="Category2" Output="2"></Map>
    <Map Input="Category3" Output="3"></Map>
    <Map Input="Category4" Output="4"></Map>
  </Transform>
</Config>

Вот мой первый опыт создания типов для десериализации в них. Данные должным образом десериализованы в эти классы, поэтому единственным оставшимся шагом является преобразование их в словарь.

    [XmlRoot]
    public class Config
    {
        [XmlElement("Transform")]
        public List<Transform> Transforms { get; set; }
    }

    public class Transform
    {
        [XmlIgnore]
        private Type inputType { get; set; }

        [XmlIgnore]
        private Type outputType { get; set; }

        [XmlAttribute]
        public string Input {
            get { return inputType.AssemblyQualifiedName; }
            set
            {
                inputType = Type.GetType(value, true);
            }
        }

        [XmlAttribute]
        public string Output
        {
            get { return outputType.AssemblyQualifiedName; }
            set
            {
                outputType = Type.GetType(value, true);
            }
        }

        [XmlElement("Map")]
        public List<Map> Mappings { get; set; }
    }

    public class Map
    {
        [XmlAttribute]
        public string Input { get; set; }

        [XmlAttribute]
        public string Output { get; set; }
    }

Моя первоначальная стратегия заключалась в том, чтобы найти способ использовать объекты System.Type для добавления функции к класс преобразования, который будет возвращать соответствующий словарь, но лучшее, что я мог узнать, это вернуть Dictionary<object, object>.

  • Может быть, есть какой-то способ сделать класс Transform generi c ?
  • Может быть, Dictionary<T, U> не правильная цель, но какая-то другая структура подойдет лучше? (Потребитель этих словарей ожидает IEnumerable<KeyValuePair<string, bool>> для первого преобразования)

EDIT: конечной целью будет иметь словарь <string, bool> для первого преобразования в XML и словарь <string, int>.

1 Ответ

0 голосов
/ 07 февраля 2020

Попробуйте следующее:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;


namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            Dictionary<Type, Dictionary<Type, List<KeyValuePair<string, Boolean>>>> dict = doc.Descendants("Transform")
                .GroupBy(x => Type.GetType((string)x.Attribute("Input")), y => y)
                .ToDictionary(x => x.Key, y => y.GroupBy(a => Type.GetType((string)a.Attribute("Output")), b => b.Elements("Map").Select(c => new KeyValuePair<string, Boolean>((string)c.Attribute("Input"), (string)c.Attribute("Output") == "true" ? true : false)).ToList())
                    .ToDictionary(a => a.Key, b => b.FirstOrDefault()));

        }
    }
}
...