XmlSerializer 不会序列化 IEnumerable

发布于 2025-01-01 11:31:21 字数 454 浏览 4 评论 0原文

我有一个调用记录器,旨在使用 XmlSerializer 记录所有方法调用以及与该方法关联的参数。它适用于大多数调用,但对于具有 IEnumerable 类型参数的所有方法都会引发异常。

例如,void MethodWithPlace( Place value ) 将被序列化,但 void MethodWithPlace( IEnumerablevalue ) 则不会。

例外的是

System.NotSupportedException:无法序列化接口 System.Collections.Generic.IEnumerable`1[[地点, 测试,版本=0.0.0.0,文化=中性]]。

我应该怎么做才能使其与那些以 IEnumerable 作为其参数之一的方法一起工作?

I have an invocation logger that is intended to record all method calls along with the parameters associated with the method using XmlSerializer. It works well for most of the calls, but it throws an exception for all methods that has a parameter of IEnumerable type.

For example, void MethodWithPlace( Place value ) would be serialized, but void MethodWithPlace( IEnumerable<Place> value ) would not.

The exception is

System.NotSupportedException: Cannot serialize interface
System.Collections.Generic.IEnumerable`1[[Place,
Test, Version=0.0.0.0, Culture=neutral]].

What should I do to make it work with those methods with IEnumerable as one of its parameters?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

べ繥欢鉨o。 2025-01-08 11:31:21

序列化 IEnumerable 属性的方式是使用代理属性,

[XmlRoot]
public class Entity {
   [XmlIgnore]
   public IEnumerable<Foo> Foo { get; set; }

   [XmlElement, Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
   public List<Foo> FooSurrogate { get { return Foo.ToList(); } set { Foo = value; } }
}

这很丑陋,但它可以完成工作。更好的解决方案是编写一个代理类(即EntitySurrogate)。

The way you serialize an IEnumerable property is with a surrogate property

[XmlRoot]
public class Entity {
   [XmlIgnore]
   public IEnumerable<Foo> Foo { get; set; }

   [XmlElement, Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
   public List<Foo> FooSurrogate { get { return Foo.ToList(); } set { Foo = value; } }
}

It's ugly, but it gets the job done. The nicer solution is to write a surrogate class (i.e. EntitySurrogate).

青柠芒果 2025-01-08 11:31:21

我认为你无法将其连载。尝试将 IEnumerable 转换为 List,然后您就可以序列化。

I don't think you'll be able to serialize that. Try converting the IEnumerable to a List and then you will be able to serialize.

深者入戏 2025-01-08 11:31:21

基本上,XmlSerializer 无法序列化接口。那么,解决方案就是给它一个具体的实例来序列化。根据您的调用记录器的工作方式,我会考虑使用

var serializer = new XmlSerializer(value.GetType());

Basically an XmlSerializer can't serialize an interface. The solution, then, is to give it a concrete instance to serialize. Depending on how your invocation logger works, I would consider using

var serializer = new XmlSerializer(value.GetType());
满意归宿 2025-01-08 11:31:21

要实现 XML 可序列化,从 IEnumerable 继承的类型必须在其继承层次结构的所有级别都具有 Add(System.Object) 实现。 {您的类} 未实现 Add(System.Object)。

实现Add()函数,你可能会解决问题

To be XML serializable, types which inherit from IEnumerable must have an implementation of Add(System.Object) at all levels of their inheritance hierarchy. {your class} does not implement Add(System.Object).

implement the Add() function, you might solve the problem

如若梦似彩虹 2025-01-08 11:31:21

XmlSerializer 不支持此功能。尝试 YAXLib 进行这些类型的序列化。

XmlSerializer does not support this. Try YAXLib for these kinds serializations.

计㈡愣 2025-01-08 11:31:21

也许不是最好的方法,但它对我有用。
我创建了一个进行序列化的方法。

使用

var xml = Util.ObjetoToXML(obj, null, null).OuterXml;

方法

        public static XmlDocument ObjetoToXML(object obj, XmlDocument xmlDocument, XmlNode rootNode)
    {

        if (xmlDocument == null)
            xmlDocument = new XmlDocument();

        if (obj == null) return xmlDocument;

        Type type = obj.GetType();

        if (rootNode == null) { 
            rootNode = xmlDocument.CreateElement(string.Empty, type.Name, string.Empty);
            xmlDocument.AppendChild(rootNode);
        }

        if (type.IsPrimitive || type == typeof(Decimal) || type == typeof(String) || type == typeof(DateTime))
        {

            // Simples types
            if (obj != null)
                rootNode.InnerText = obj.ToString();

        }
        else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
        {
            // Genericis types

            XmlNode node = null;

            foreach (var item in (IEnumerable)obj)
            {
                if (node == null)
                {
                    node = xmlDocument.CreateElement(string.Empty, item.GetType().Name, string.Empty);
                    node = rootNode.AppendChild(node);
                }


                ObjetoToXML(item, xmlDocument, node);
            }

        }
        else
        {

            // Classes types
            foreach (var propertie in obj.GetType().GetProperties())
            {

                XmlNode node = xmlDocument.CreateElement(string.Empty, propertie.Name, string.Empty);
                node = rootNode.AppendChild(node);
                var valor = propertie.GetValue(obj, null);

                ObjetoToXML(valor, xmlDocument, node);
            }

        }


        return xmlDocument;

    }

Maybe not the best way, but it worked for me.
I created a method that makes serialization.

Use

var xml = Util.ObjetoToXML(obj, null, null).OuterXml;

method

        public static XmlDocument ObjetoToXML(object obj, XmlDocument xmlDocument, XmlNode rootNode)
    {

        if (xmlDocument == null)
            xmlDocument = new XmlDocument();

        if (obj == null) return xmlDocument;

        Type type = obj.GetType();

        if (rootNode == null) { 
            rootNode = xmlDocument.CreateElement(string.Empty, type.Name, string.Empty);
            xmlDocument.AppendChild(rootNode);
        }

        if (type.IsPrimitive || type == typeof(Decimal) || type == typeof(String) || type == typeof(DateTime))
        {

            // Simples types
            if (obj != null)
                rootNode.InnerText = obj.ToString();

        }
        else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
        {
            // Genericis types

            XmlNode node = null;

            foreach (var item in (IEnumerable)obj)
            {
                if (node == null)
                {
                    node = xmlDocument.CreateElement(string.Empty, item.GetType().Name, string.Empty);
                    node = rootNode.AppendChild(node);
                }


                ObjetoToXML(item, xmlDocument, node);
            }

        }
        else
        {

            // Classes types
            foreach (var propertie in obj.GetType().GetProperties())
            {

                XmlNode node = xmlDocument.CreateElement(string.Empty, propertie.Name, string.Empty);
                node = rootNode.AppendChild(node);
                var valor = propertie.GetValue(obj, null);

                ObjetoToXML(valor, xmlDocument, node);
            }

        }


        return xmlDocument;

    }
无敌元气妹 2025-01-08 11:31:21

您可以使用 DataContractSerializer

        using (var ms = new MemoryStream())
        {
            var serialiser = new DataContractSerializer(typeof (EnvironmentMetadata));
            serialiser.WriteObject(ms, environmentMetadata);

            var s = Encoding.ASCII.GetString(ms.ToArray());
            return s;
        }

You can use DataContractSerializer

        using (var ms = new MemoryStream())
        {
            var serialiser = new DataContractSerializer(typeof (EnvironmentMetadata));
            serialiser.WriteObject(ms, environmentMetadata);

            var s = Encoding.ASCII.GetString(ms.ToArray());
            return s;
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文