C#: объект Рендеринга как XML

Вы можете заключить свой div в фрагмент React и ставить <br> после каждого div.

6
задан Paul Stovell 23 February 2009 в 18:27
поделиться

3 ответа

Это кажется, что было бы просто для записи отражения использования: приведенный пример объекта, создайте элемент XML с его именем класса и затем выполните итерации через все его свойства.

Поскольку каждое свойство создает элемент со своим именем:

  • если это - тип значения, установите его текст на текст XML-схемы его значения;
  • если это реализует IEnumerable, выполните итерации через него и создайте элемент для каждого объекта;
  • если это - какой-либо другой ссылочный тип, установите содержание элемента на представление свойства XML.

Отследите круговые/несколько ссылки с HashSet, содержащим хэш-коды каждого объекта, который Вы сериализировали; при нахождении хэш-кода объекта в HashSet Вы уже сериализировали его. (Я не знаю то, что Вы хотите помещенный в XML, если это происходит.)

Но не, у меня нет кода, который делает эту ложь вокруг.

4
ответ дан 9 December 2019 в 22:40
поделиться

Сообщение Robert Rossney заставило меня думать, что это - вероятно, меньше работы, чем я думал. Таким образом, вот очень грубая попытка. Это обрабатывает следующее:

  • Если это не может считать свойство, это печатает исключение как значение
  • Циклические ссылки и несколько случаев. Это связывает идентификатор с каждым элементом; если элемент появляется дважды, он просто указывает касательно идентификатора. Касательно идентификатора уникально для графа объектов (я должен, вероятно, использовать GUID, но это удовлетворяет моим целям).
  • Это не имеет никаких проблем с производными типами
  • Это не требует никаких атрибутов или определенных конструкторов или другой ерунды
  • Это может обработать свойства только для чтения

Вот пример вывода (в моих тестовых объектах, продукт "Валюты" на Порядке выдает исключение).

<Customer Ref="1">
  <FirstName>Paul</FirstName>
  <LastName>Stovell</LastName>
  <FullName>Paul Stovell</FullName>
  <Orders>
    <Order Ref="2">
      <SKU>Apples</SKU>
      <Price>27.30</Price>
      <Currency>Something bad happened</Currency>
      <Customer Ref="1" />
    </Order>
    <Order Ref="3">
      <SKU>Pears</SKU>
      <Price>17.85</Price>
      <Currency>Something bad happened</Currency>
      <Customer Ref="1" />
    </Order>
    <Order Ref="2" />
  </Orders>
</Customer>

Вот демонстрационная объектная модель и использование:

static void Main(string[] args)
{
    var customer = new Customer();
    customer.FirstName = "Paul";
    customer.LastName = "Stovell";
    customer.Orders.Add(new Order(customer) { Price = 27.30M, SKU = "Apples"});
    customer.Orders.Add(new Order(customer) { Price = 17.85M, SKU = "Pears"});
    customer.Orders.Add(customer.Orders[0]);

    var output = new StringWriter();
    var writer = new XmlTextWriter(output);
    writer.Formatting = Formatting.Indented;
    WriteComplexObject("Customer", customer, writer);
    Console.WriteLine(output.ToString());
    Console.ReadKey();
}

class Customer
{
    private readonly List<Order> _orders = new List<Order>();

    public Customer()
    {
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }

    public string FullName
    {
        // Read-only property test
        get { return FirstName + " " + LastName; }
    }

    public List<Order> Orders
    {
        // Collections test
        get { return _orders; }
    }
}

class Order
{
    private readonly Customer _customer;

    public Order(Customer customer)
    {
        _customer = customer;
    }

    public string SKU { get; set; }
    public decimal Price { get; set; }
    public string Currency
    {
        // A proprty that, for some reason, can't be read
        get
        {
            throw new Exception("Something bad happened");
        }
    }

    public Customer Customer
    {
        get { return _customer; }
    }
}

Вот реализация:

public static void WriteObject(string name, object target, XmlWriter writer)
{
    WriteObject(name, target, writer, new List<object>(), 0, 10, -1);
}

private static void WriteObject(string name, object target, XmlWriter writer, List<object> recurringObjects, int depth, int maxDepth, int maxListLength)
{
    var formatted = TryToFormatPropertyValueAsString(target);
    if (formatted != null)
    {
        WriteSimpleProperty(name, formatted, writer);
    }
    else if (target is IEnumerable)
    {
        WriteCollectionProperty(name, (IEnumerable)target, writer, depth, maxDepth, recurringObjects, maxListLength);
    }
    else
    {
        WriteComplexObject(name, target, writer, recurringObjects, depth, maxDepth, maxListLength);
    }
}

private static void WriteComplexObject(string name, object target, XmlWriter writer, List<object> recurringObjects, int depth, int maxDepth, int maxListLength)
{
    if (target == null || depth >= maxDepth) return;
    if (recurringObjects.Contains(target))
    {
        writer.WriteStartElement(name);
        writer.WriteAttributeString("Ref", (recurringObjects.IndexOf(target) + 1).ToString());
        writer.WriteEndElement();
        return;
    }
    recurringObjects.Add(target);

    writer.WriteStartElement(name);
    writer.WriteAttributeString("Ref", (recurringObjects.IndexOf(target) + 1).ToString());
    foreach (var property in target.GetType().GetProperties())
    {
        var propertyValue = ReadPropertyValue(target, property);
        WriteObject(property.Name, propertyValue, writer, recurringObjects, depth + 1, maxDepth, maxListLength);
    }
    writer.WriteEndElement();
}

private static object ReadPropertyValue(object target, PropertyInfo property)
{
    try { return property.GetValue(target, null); }
    catch (Exception ex) { return ReadExceptionMessage(ex); }
}

private static string ReadExceptionMessage(Exception ex)
{
    if (ex is TargetInvocationException && ex.InnerException != null)
        return ReadExceptionMessage(ex.InnerException);
    return ex.Message;
}

private static string TryToFormatPropertyValueAsString(object propertyValue)
{
    var formattedPropertyValue = null as string;
    if (propertyValue == null)
    {
        formattedPropertyValue = string.Empty;
    }
    else if (propertyValue is string || propertyValue is IFormattable || propertyValue.GetType().IsPrimitive)
    {
        formattedPropertyValue = propertyValue.ToString();
    }
    return formattedPropertyValue;
}

private static void WriteSimpleProperty(string name, string formattedPropertyValue, XmlWriter writer)
{
    writer.WriteStartElement(name);
    writer.WriteValue(formattedPropertyValue);
    writer.WriteEndElement();
}

private static void WriteCollectionProperty(string name, IEnumerable collection, XmlWriter writer, int depth, int maxDepth, List<object> recurringObjects, int maxListLength)
{
    writer.WriteStartElement(name);
    var enumerator = null as IEnumerator;
    try
    {
        enumerator = collection.GetEnumerator();
        for (var i = 0; enumerator.MoveNext() && (i < maxListLength || maxListLength == -1); i++)
        {
            if (enumerator.Current == null) continue;
            WriteComplexObject(enumerator.Current.GetType().Name, enumerator.Current, writer, recurringObjects, depth + 1, maxDepth, maxListLength);
        }
    }
    catch (Exception ex)
    {
        writer.WriteElementString(ex.GetType().Name, ReadExceptionMessage(ex));
    }
    finally
    {
        var disposable = enumerator as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
        }
        writer.WriteEndElement();
    }
}

Мне все еще было бы интересно знать, существует ли больше проверенных на практике решений.

6
ответ дан 9 December 2019 в 22:40
поделиться

Я сомневаюсь, что Вы собираетесь найти что-либо, что работает особенно хорошо через все классы. Как Вы указали, XmlSerializer является максимальными усилиями Microsoft в универсальном конце вещей до сих пор.

На другом конце visualizers, которые уникальны для определенного класса. Я не думаю, что существует большая часть золотой середины все же.

1
ответ дан 9 December 2019 в 22:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: