Могу ли я сериализовать анонимные типы как xml?

Я понял, что анонимные типы помечаются компилятором как закрытые, а свойства доступны только для чтения. Есть ли способ сериализовать их в xml (без десериализации)? Он работает с JSON, как я могу сделать это с помощью XML?


person Radu    schedule 08.03.2010    source источник


Ответы (9)


Этого нельзя добиться ни с помощью XmlSerializer, ни DataContractSerializer. Это можно сделать с помощью кода, написанного вручную, как показано ниже (я не могу прокомментировать, является ли код исчерпывающим. достаточно, чтобы справиться со всеми типами - но это очень хорошее начало).

person John Saunders    schedule 08.03.2010
comment
Однако это не значит, что вы не можете сделать это со сторонним классом. - person Matthew Flaschen; 09.03.2010
comment
можно ли написать что-нибудь общее? - person Radu; 09.03.2010
comment
@Radu: Я не понимаю, что вы имеете в виду, напишите что-нибудь общее. Нет, если вы говорите об использовании сериализатора XML. Ответ Мэтью Уитеда показывает, как это сделать без использования сериализатора XML. - person John Saunders; 09.03.2010
comment
Вероятно, это один из тех, кто отрицает все ответы, которые не помечены как правильные. Жаль, что люди не видят, что вы правы и в том, что встроенный XML-сериализатор не будет работать. - person Matthew Whited; 09.03.2010
comment
Я верю, что ответ Мэтьюза, приведенный ниже, является правильным. Я взял его код, и он сразу заработал - я внес некоторые изменения, чтобы он поддерживал массивы: martinnormark.com/ - person MartinHN; 05.02.2011
comment
Кто-нибудь знает, есть ли проблема для этого? - person George Mauer; 31.08.2014
comment
@GeorgeMauer: что за проблема? Именно так ведет себя сериализатор XML с первого дня. - person John Saunders; 31.08.2014
comment
Да, но для webapi по-прежнему не рекомендуется случайным образом выдавать ошибки по умолчанию при выполнении действий, которые, как было бы разумно ожидать, сработают. Мне не удалось найти ни одного запроса функции, поэтому я создал его - person George Mauer; 31.08.2014
comment
@GeorgeMauer: какое это имеет отношение к веб-API? Я не думаю, что он вообще существовал, когда был задан этот вопрос. Вы отвечаете на правильный вопрос? - person John Saunders; 31.08.2014
comment
Я понимаю, да, мой контекст здесь не применим. Было бы неплохо создать проблему, чтобы исправить это поведение напрямую в XmlSerializer. Я даже не знаю, где может быть этот трекер проблем. Возможно, пользовательский голос Visual Studio? Похоже, они, по крайней мере, отслеживают запросы функций C #. - person George Mauer; 01.09.2014
comment
@GeorgeMauer: сериализатор XML больше не поддерживается, поэтому для этого не было бы средства отслеживания проблем. - person John Saunders; 01.09.2014

Что-то вроде этого должно вас начать ...

class Program
{
    static void Main(string[] args)
    {
        var me = new
        {
            Hello = "World",
            Other = new
            {
                My = "Object",
                V = 1,
                B = (byte)2
            }
        };

        var x = me.ToXml();
    }
}
public static class Tools
{
    private static readonly Type[] WriteTypes = new[] {
        typeof(string), typeof(DateTime), typeof(Enum), 
        typeof(decimal), typeof(Guid),
    };
    public static bool IsSimpleType(this Type type)
    {
        return type.IsPrimitive || WriteTypes.Contains(type);
    }
    public static XElement ToXml(this object input)
    {
        return input.ToXml(null);
    }
    public static XElement ToXml(this object input, string element)
    {
        if (input == null)
            return null;

        if (string.IsNullOrEmpty(element))
            element = "object";
        element = XmlConvert.EncodeName(element);
        var ret = new XElement(element);

        if (input != null)
        {
            var type = input.GetType();
            var props = type.GetProperties();

            var elements = from prop in props
                           let name = XmlConvert.EncodeName(prop.Name)
                           let val = prop.GetValue(input, null)
                           let value = prop.PropertyType.IsSimpleType()
                                ? new XElement(name, val)
                                : val.ToXml(name)
                           where value != null
                           select value;

            ret.Add(elements);
        }

        return ret;
    }
}

... результирующий xml ...

<object>
  <Hello>World</Hello>
  <Other>
    <My>Object</My>
    <V>1</V>
    <B>2</B>
  </Other>
</object>
person Matthew Whited    schedule 08.03.2010
comment
Думаю, Type.IsValueType может быть хорошим ярлыком для большинства IsAssignableFrom s. Однако не ловит string. - person sunside; 16.08.2010
comment
IsValueType может быть неправильным выбором. Это будет использовать значение ToString для преобразования типа. Но я внес изменение, которое должно быть намного легче понять. - person Matthew Whited; 16.08.2010
comment
Эй, ваш код работает как шарм. Я внес небольшие изменения, чтобы он поддерживал массивы, я написал об этом здесь: martinnormark.com/ - person MartinHN; 05.02.2011
comment
Хорошо, это хороший образец ... теперь, как я могу сериализовать объекты, которые содержат анонимные типы ... я полагаю, с помощью настраиваемой сериализации ... - person serhio; 06.10.2011
comment
Это может быть бесполезно для многих людей, но это правильный ответ на этот конкретный вопрос. - person nik.shornikov; 26.09.2013
comment
Вот сообщение в блоге, которое, вероятно, было вдохновлено этим ответом: martinnormark .com / - person Cristian Diaconescu; 14.03.2014

Спасибо, отличная работа @Matthew и @Martin.

Я сделал несколько модификаций, чтобы приспособить Nullables и Enums. Также я изменил его так, чтобы элементы массива назывались в соответствии с именем свойства + индекс.

Вот код, если кому интересно

public static class ObjectExtensions {
    #region Private Fields
    private static readonly Type[] WriteTypes = new[] {
        typeof(string), typeof(DateTime), typeof(Enum), 
        typeof(decimal), typeof(Guid),
    };
    #endregion Private Fields
    #region .ToXml
    /// <summary>
    /// Converts an anonymous type to an XElement.
    /// </summary>
    /// <param name="input">The input.</param>
    /// <returns>Returns the object as it's XML representation in an XElement.</returns>
    public static XElement ToXml(this object input) {
        return input.ToXml(null);
    }

    /// <summary>
    /// Converts an anonymous type to an XElement.
    /// </summary>
    /// <param name="input">The input.</param>
    /// <param name="element">The element name.</param>
    /// <returns>Returns the object as it's XML representation in an XElement.</returns>
    public static XElement ToXml(this object input, string element) {
        return _ToXml(input, element);
    }

    private static XElement _ToXml(object input, string element, int? arrayIndex = null, string arrayName = null) {
        if (input == null)
            return null;

        if (String.IsNullOrEmpty(element)) {
            string name = input.GetType().Name;
            element = name.Contains("AnonymousType") 
                ? "Object" 
                : arrayIndex != null
                    ? arrayName + "_" + arrayIndex
                    : name;
        }

        element = XmlConvert.EncodeName(element);
        var ret = new XElement(element);

        if (input != null) {
            var type = input.GetType();
            var props = type.GetProperties();

            var elements = props.Select(p => {
                var pType = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType;
                var name = XmlConvert.EncodeName(p.Name);
                var val = pType.IsArray ? "array" : p.GetValue(input, null);
                var value = pType.IsArray 
                    ? GetArrayElement(p, (Array)p.GetValue(input, null))
                    : pType.IsSimpleType() || pType.IsEnum 
                        ? new XElement(name, val) 
                        : val.ToXml(name);
                return value;
            })
            .Where(v=>v !=null);

            ret.Add(elements);
        }

        return ret;
    }

    #region helpers
    /// <summary>
    /// Gets the array element.
    /// </summary>
    /// <param name="info">The property info.</param>
    /// <param name="input">The input object.</param>
    /// <returns>Returns an XElement with the array collection as child elements.</returns>
    private static XElement GetArrayElement(PropertyInfo info, Array input) {
        var name = XmlConvert.EncodeName(info.Name);

        XElement rootElement = new XElement(name);

        var arrayCount = input == null ? 0 : input.GetLength(0);

        for (int i = 0; i < arrayCount; i++) {
            var val = input.GetValue(i);
            XElement childElement = val.GetType().IsSimpleType() ? new XElement(name + "_" + i, val) : _ToXml(val, null, i, name);

            rootElement.Add(childElement);
        }

        return rootElement;
    }

    #region .IsSimpleType
    public static bool IsSimpleType(this Type type) {
        return type.IsPrimitive || WriteTypes.Contains(type);
    }
    #endregion .IsSimpleType

    #endregion helpers
    #endregion .ToXml
}
person ricardo    schedule 25.06.2011
comment
Это хороший код (уже +1), но он не обрабатывает списки (список должен быть преобразован в массивы, .ToArray (), что не всегда возможно). - person rufo; 29.05.2013

Я знаю, что это старый пост, но мое решение преобразует анонимный тип в XML всего за 2 строки кода.

Сначала преобразуйте анонимный тип в JSON, а затем из JSON в XML.

var jsonText = JsonConvert.SerializeObject(data);           // convert to JSON
XmlDocument doc = JsonConvert.DeserializeXmlNode(jsonText); // convert JSON to XML Document

Образец

var data = new       // data - Anonymous Type
{
    Request = new
    {
        OrderNumber = 123,
        Note = "Hello World"
    }
};

var jsonText = JsonConvert.SerializeObject(data);           
XmlDocument doc = JsonConvert.DeserializeXmlNode(jsonText);

Console.WriteLine(doc.OuterXml);                            

Вывод

<Request>
    <OrderNumber>123</OrderNumber>
    <Note>Hello World</Note>
</Request>
person Pavel    schedule 04.10.2019
comment
Я искал что-то в этом роде. Есть накладные расходы, но пока это самое простое решение. +1 - person T-moty; 30.12.2019

Моя собственная версия тогдашней прекрасной работы @Matthew и @Martin: теперь поддерживаются массивы перечислений, а понятие массивов обобщено в IEnumerable, чтобы также поддерживать всевозможные коллекции.

public static class ObjectExtensions {
/// <summary>
/// Converts an anonymous type to an XElement.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>Returns the object as it's XML representation in an XElement.</returns>
public static XElement ToXml2(this object input) {
    return input.ToXml2(null);
}

/// <summary>
/// Converts an anonymous type to an XElement.
/// </summary>
/// <param name="input">The input.</param>
/// <param name="element">The element name.</param>
/// <returns>Returns the object as it's XML representation in an XElement.</returns>
public static XElement ToXml2(this object input, string element) {
    return _ToXml(input, element);
}

private static XElement _ToXml(object input, string element, int? arrayIndex = null, string arrayName = null) {
    if (input == null)
        return null;

    if (String.IsNullOrEmpty(element)) {
        string name = input.GetType().Name;
        element = name.Contains("AnonymousType") 
            ? "Object" 
            : arrayIndex != null
                ? arrayName + "_" + arrayIndex
                : name;
    }

    element = XmlConvert.EncodeName(element);
    var ret = new XElement(element);

    if (input != null) {
        var type = input.GetType();
        var props = type.GetProperties();

        var elements = props.Select(p => {
            var pType = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType;
            var name = XmlConvert.EncodeName(p.Name);
            var val = pType.IsArray ? "array" : p.GetValue(input, null);
            var value = pType.IsEnumerable()
                ? GetEnumerableElements(p, (IEnumerable)p.GetValue(input, null))
                : pType.IsSimpleType2() || pType.IsEnum 
                    ? new XElement(name, val) 
                    : val.ToXml2(name);
            return value;
        })
        .Where(v=>v !=null);

        ret.Add(elements);
    }

    return ret;
}

#region helpers

private static XElement GetEnumerableElements(PropertyInfo info, IEnumerable input) {
    var name = XmlConvert.EncodeName(info.Name);

    XElement rootElement = new XElement(name);

    int i = 0;
    foreach(var v in input)
    {
        XElement childElement = v.GetType().IsSimpleType2() || v.GetType().IsEnum ? new XElement(name + "_" + i, v) : _ToXml(v, null, i, name);
        rootElement.Add(childElement);
        i++;
    }
    return rootElement;
}

private static readonly Type[] WriteTypes = new[] {
    typeof(string), typeof(DateTime), typeof(Enum), 
    typeof(decimal), typeof(Guid),
};
public static bool IsSimpleType2(this Type type) {
    return type.IsPrimitive || WriteTypes.Contains(type);
}

private static readonly Type[] FlatternTypes = new[] {
    typeof(string)
};
public static bool IsEnumerable(this Type type) {
    return typeof(IEnumerable).IsAssignableFrom(type) && !FlatternTypes.Contains(type);
}
#endregion
}
person VdesmedT    schedule 10.03.2015

В приведенном ниже ответе IEnumerables обрабатывается так, как мне было нужно, и изменит это:

new
{
    Foo = new[]
    {
        new { Name = "One" },
        new { Name = "Two" },
    },
    Bar = new[]
    {
        new { Name = "Three" },
        new { Name = "Four" },
    },
}

в это:

<object>
    <Foo><Name>One</Name></Foo>
    <Foo><Name>Two</Name></Foo>
    <Bar><Name>Three</Name></Bar>
    <Bar><Name>Four</Name></Bar>
</object>

Итак, вот вам еще один вариант ответа Матфея:

public static class Tools
{
    private static readonly Type[] WriteTypes = new[] {
        typeof(string),
        typeof(Enum),
        typeof(DateTime), typeof(DateTime?),
        typeof(DateTimeOffset), typeof(DateTimeOffset?),
        typeof(int), typeof(int?),
        typeof(decimal), typeof(decimal?),
        typeof(Guid), typeof(Guid?),
    };
    public static bool IsSimpleType(this Type type)
    {
        return type.IsPrimitive || WriteTypes.Contains(type);
    }
    public static object ToXml(this object input)
    {
        return input.ToXml(null);
    }
    public static object ToXml(this object input, string element)
    {
        if (input == null)
            return null;

        if (string.IsNullOrEmpty(element))
            element = "object";
        element = XmlConvert.EncodeName(element);
        var ret = new XElement(element);

        if (input != null)
        {
            var type = input.GetType();

            if (input is IEnumerable && !type.IsSimpleType())
            {
                var elements = (input as IEnumerable<object>)
                    .Select(m => m.ToXml(element))
                    .ToArray();

                return elements;
            }
            else
            {
                var props = type.GetProperties();

                var elements = from prop in props
                               let name = XmlConvert.EncodeName(prop.Name)
                               let val = prop.GetValue(input, null)
                               let value = prop.PropertyType.IsSimpleType()
                                    ? new XElement(name, val)
                                    : val.ToXml(name)
                               where value != null
                               select value;

                ret.Add(elements);
            }
        }

        return ret;
    }
}
person Jeremy Cook    schedule 16.03.2016

Моя первая публикация, посвященная веб-сайту, который всегда очень помогает. Bellow - это полное решение, которое можно использовать с ядром .net (протестировано с использованием 3.1), просто вызовите ConvertAnonymousToType.Convert ("MyNewType", target, out Type newType) Возврат будет объектом, который вы можете использовать для возврата внутри контроллера или для сериализации вручную (System.Xml.Serialization.XmlSerializer). Использование объекта в качестве возврата Внутри контроллера: 1. настройте службу (Startup.cs> ConfigureServices> services.AddMvcCore (options => options.OutputFormatters.Add (new XmlSerializerOutputFormatter ());),
2. Целевое действие : используйте [FormatFilter] и [Route ("....... {format}")], 3. Верните объект

Если для составления ответа требуется какой-либо дополнительный анонимный тип (метаданные, набор результатов и т. Д.), DynamicTypeBuilder.CreateNewObject может использоваться для обслуживания :)

Еще раз спасибо

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;


namespace Configuration
{
public static class DynamicTypeBuilder
{
    public static object CreateNewObject(string typeName, Dictionary<string, Type> properties, out Type newType)
    {
        newType = CompileResultType(typeName, properties);
        return Activator.CreateInstance(newType);
    }

    public static Type CompileResultType(string typeName, Dictionary<string, Type> properties)
    {
        TypeBuilder tb = GetTypeBuilder(typeName);
        ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

        //Add properties
        properties.ToList().ForEach(p => CreateProperty(tb, p.Key, p.Value));

        //Created Type with properties
        Type objectType = tb.CreateType();
        return objectType;
    }

    //Create Type with an standard configuration
    private static TypeBuilder GetTypeBuilder(string typeName)
    {
        string assemblyName = typeName + "InternalAssembly";
        var an = new AssemblyName(assemblyName);
        AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
        ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
        TypeBuilder tb = moduleBuilder.DefineType(typeName,
                TypeAttributes.Public |
                TypeAttributes.Class |
                TypeAttributes.AutoClass |
                TypeAttributes.AnsiClass |
                TypeAttributes.BeforeFieldInit |
                TypeAttributes.AutoLayout,
                null);
        return tb;
    }

    private static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType)
    {
        FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);

        PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
        MethodBuilder getPropMthdBldr = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
        ILGenerator getIl = getPropMthdBldr.GetILGenerator();

        getIl.Emit(OpCodes.Ldarg_0);
        getIl.Emit(OpCodes.Ldfld, fieldBuilder);
        getIl.Emit(OpCodes.Ret);

        MethodBuilder setPropMthdBldr =
            tb.DefineMethod("set_" + propertyName,
              MethodAttributes.Public |
              MethodAttributes.SpecialName |
              MethodAttributes.HideBySig,
              null, new[] { propertyType });

        ILGenerator setIl = setPropMthdBldr.GetILGenerator();
        Label modifyProperty = setIl.DefineLabel();
        Label exitSet = setIl.DefineLabel();

        setIl.MarkLabel(modifyProperty);
        setIl.Emit(OpCodes.Ldarg_0);
        setIl.Emit(OpCodes.Ldarg_1);
        setIl.Emit(OpCodes.Stfld, fieldBuilder);

        setIl.Emit(OpCodes.Nop);
        setIl.MarkLabel(exitSet);
        setIl.Emit(OpCodes.Ret);

        propertyBuilder.SetGetMethod(getPropMthdBldr);
        propertyBuilder.SetSetMethod(setPropMthdBldr);
    }
}

public static class ConvertAnonymousToType
{
    public static object Convert(string typeName, object target, out Type newType)
    {
        var properties = GetProperties(target);
        newType = DynamicTypeBuilder.CompileResultType(typeName, properties);
        return Convert(newType, target);
    }

    public static object Convert(Type type, object target)
    {
        if (target.GetType().Name == typeof(List<>).Name)
        {
            var newListType = typeof(List<>).MakeGenericType(type);
            var newList = Activator.CreateInstance(newListType);
            MethodInfo addMethod = newList.GetType().GetMethod("Add");
            ((IList<object>)target).ToList().ForEach(e =>
            {
                addMethod.Invoke(newList, new object[] { ConvertObject(type, e) });
            });
            return newList;
        }
        else
        {
            return ConvertObject(type, target);
        }
    }

    private static object ConvertObject(Type type, object refObject)
    {
        Dictionary<string, Type> properties = new Dictionary<string, Type>();
        object newObject = Activator.CreateInstance(type);
        var propertiesOrg = refObject.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
        var propertiesDes = newObject.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
        propertiesOrg.ForEach(po => propertiesDes.First(pd => pd.Name == po.Name).SetValue(newObject, po.GetValue(refObject)));
        return newObject;
    }

    private static Dictionary<string, Type> GetProperties(object target)
    {
        object objectRef = target;
        if (target.GetType().Name == typeof(List<>).Name) objectRef = ((List<object>)target).ToList()[0];

        Dictionary<string, Type> properties = new Dictionary<string, Type>();
        var lstProperties = objectRef.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
        lstProperties.ForEach(p => properties.Add(p.Name, p.PropertyType));
        return properties;
    }

}
}
person Gil    schedule 07.02.2020

Я нашел эту страницу чрезвычайно полезной. Я перехожу от старых веб-ссылок SOAP к тому, что поддерживается стандартом .net. Я изменил код, чтобы иметь возможность сериализовать его в формате, который будет работать с веб-службами SOAP. Это грубо, но он может преобразовывать object[] в <anyType /> элементы, другие простые массивы сериализованы правильно, и вы можете передать пространство имен или использовать XmlTypeAttribute в ваших моделях для назначения пространств имен.

public static class AnonymousTypeSerializer
{
    private static XNamespace _xmlInstanceNs = "http://www.w3.org/2001/XMLSchema-instance";

    private static readonly Type[] WriteTypes = new[] {
        typeof(string), typeof(DateTime), typeof(Enum),
        typeof(decimal), typeof(Guid),
    };

    private static readonly Dictionary<Type, string> SerializedTypeNames = new Dictionary<Type, string>()
    {
        { typeof(int), "int" },
        { typeof(long), "long" }
    };

    /// <summary>
    /// Converts an anonymous type to an XElement.
    /// </summary>
    /// <param name="input">The input.</param>
    /// <returns>Returns the object as it's XML representation in an XElement.</returns>
    public static XElement ToXml(this object input)
    {
        return input.ToXml(null);
    }

    /// <summary>
    /// Converts an anonymous type to an XElement.
    /// </summary>
    /// <param name="input">The input.</param>
    /// <param name="element">The element name.</param>
    /// <returns>Returns the object as it's XML representation in an XElement.</returns>
    public static XElement ToXml(this object input, string element, XNamespace ns = null)
    {
        return _ToXml(input, element, ns ?? XNamespace.None);
    }

    private static XElement _ToXml(object input, string element, XNamespace ns = null, int? arrayIndex = null, string arrayName = null)
    {
        if (input == null)
            return null;

        if (string.IsNullOrEmpty(element))
        {
            string name = input.GetType().Name;
            element = name.Contains("AnonymousType")
                ? "Object"
                : arrayIndex != null
                    ? $"{arrayName}"
                    : name;
        }

        element = XmlConvert.EncodeName(element);
        XElement ret = new XElement(ns.GetName(element));

        if (input != null)
        {
            var type = input.GetType();
            var props = type.GetProperties();
            var xmlType = type.GetCustomAttribute<XmlTypeAttribute>(true);

            if (xmlType != null && xmlType.Namespace != null)
                ns = xmlType.Namespace;

            ret.Add(props.Select(p =>
            {
                var pType = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType;
                var name = XmlConvert.EncodeName(p.Name);

                var val = pType.IsArray ? "array" : p.GetValue(input, null);
                var value = pType.IsArray
                    ? GetArrayElement(p, (Array)p.GetValue(input, null), ns)
                    : pType.IsSimpleType() || pType.IsEnum
                        ? new XElement(ns.GetName(name), val)
                        : val.ToXml(name, ns);

                return value;
            }).Where(v => v != null));
        }

        return ret;
    }

    /// <summary>
    /// Gets the array element.
    /// </summary>
    /// <param name="info">The property info.</param>
    /// <param name="input">The input object.</param>
    /// <returns>Returns an XElement with the array collection as child elements.</returns>
    private static XElement GetArrayElement(PropertyInfo info, Array input, XNamespace ns)
    {
        var name = XmlConvert.EncodeName(info.Name);
        var arrayCount = input == null ? 0 : input.GetLength(0);
        var elementType = input.GetType().GetElementType();
        var isAnyType = elementType == typeof(object);

        XElement rootElement;
        if (isAnyType)
            rootElement = new XElement(ns + name, new XAttribute(XNamespace.Xmlns + "xsi", _xmlInstanceNs));
        else
            rootElement = new XElement(ns + name);

        for (int i = 0; i < arrayCount; i++)
        {
            var val = input.GetValue(i);

            if (isAnyType)
            {
                var valType = val.GetType();
                var xmlType = valType.GetCustomAttribute<XmlTypeAttribute>(true);
                XNamespace valNs = ns;

                if (xmlType != null && xmlType.Namespace != null)
                    valNs = xmlType.Namespace;

                // Create anyType element
                var childElement = new XElement(ns + "anyType", new XAttribute(XNamespace.Xmlns + $"p{rootElement.Elements().Count()}", valNs));

                // Create type attribute
                var nsPrefix = childElement.GetPrefixOfNamespace(valNs);
                childElement.Add(new XAttribute(_xmlInstanceNs + "type",
                    !string.IsNullOrEmpty(nsPrefix)
                        ? $"{nsPrefix}:{valType.Name}"
                        : valType.Name));

                // Create child elements
                var inner = _ToXml(val, null, ns, i, "anyType");
                childElement.Add(inner.Elements());

                // Done
                rootElement.Add(childElement);
            }
            else
            {
                if (!SerializedTypeNames.TryGetValue(elementType, out var typeName))
                    typeName = elementType.Name;

                rootElement.Add(elementType.IsSimpleType()
                    ? new XElement(ns.GetName(typeName.ToLower()), val)
                    : _ToXml(val, null, ns, i, typeName));
            }
        }

        return rootElement;
    }

    public static bool IsSimpleType(this Type type)
    {
        return type.IsPrimitive || WriteTypes.Contains(type);
    }
}
person Douglas Marttinen    schedule 07.04.2021

Другой постер Павел упомянул об использовании методов Newtonsoft.Json для быстрого преобразования в 2 строки.

var jsonText = JsonConvert.SerializeObject(data);           
XmlDocument doc = JsonConvert.DeserializeXmlNode(jsonText);

Я бы предположил, что на самом деле это может быть одна строка кода :)

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

XmlDocument doc = JsonConvert.DeserializeXmlNode(JsonConvert.SerializeObject(data));
person randomoriginality    schedule 08.04.2021