代码之家  ›  专栏  ›  技术社区  ›  TheColonel26

尝试将类型序列化为XML时,收到错误“System.RuntimeType由于其保护级别而不可访问。”

  •  0
  • TheColonel26  · 技术社区  · 7 年前

    在这个问题上,我发现了下面的问题 https://stackoverflow.com/a/9809872/2226152 .

    // a version of System.Type that can be serialized
    [DataContract]
    public class SerializableType
    {
        public Type type;
    
        // when serializing, store as a string
        [DataMember]
        string TypeString
        {
            get
            {
                if (type == null)
                    return null;
                return type.FullName;
            }
            set
            {
                if (value == null)
                    type = null;
                else
                {
                    type = Type.GetType(value);
                }
            }
        }
    
        // constructors
        public SerializableType()
        {
            type = null;
        }
        public SerializableType(Type t)
        {
            type = t;
        }
    
        // allow SerializableType to implicitly be converted to and from System.Type
        static public implicit operator Type(SerializableType stype)
        {
            return stype.type;
        }
        static public implicit operator SerializableType(Type t)
        {
            return new SerializableType(t);
        }
    
        // overload the == and != operators
        public static bool operator ==(SerializableType a, SerializableType b)
        {
            // If both are null, or both are same instance, return true.
            if (System.Object.ReferenceEquals(a, b))
            {
                return true;
            }
    
            // If one is null, but not both, return false.
            if (((object)a == null) || ((object)b == null))
            {
                return false;
            }
    
            // Return true if the fields match:
            return a.type == b.type;
        }
        public static bool operator !=(SerializableType a, SerializableType b)
        {
            return !(a == b);
        }
        // we don't need to overload operators between SerializableType and System.Type because we already enabled them to implicitly convert
    
        public override int GetHashCode()
        {
            return type.GetHashCode();
        }
    
        // overload the .Equals method
        public override bool Equals(System.Object obj)
        {
            // If parameter is null return false.
            if (obj == null)
            {
                return false;
            }
    
            // If parameter cannot be cast to SerializableType return false.
            SerializableType p = obj as SerializableType;
            if ((System.Object)p == null)
            {
                return false;
            }
    
            // Return true if the fields match:
            return (type == p.type);
        }
        public bool Equals(SerializableType p)
        {
            // If parameter is null return false:
            if ((object)p == null)
            {
                return false;
            }
    
            // Return true if the fields match:
            return (type == p.type);
        }
    }
    

    因此,我尝试使用它,但在运行时收到以下错误。

    InvalidOperationException:由于以下原因,System.RuntimeType无法访问: 它的保护级别。只能处理公共类型。

    Here is a fiddler

    using System;
    using System.Collections.Generic;
    using System.Runtime.Serialization;
    using System.Xml;
    using System.Xml.Serialization;
    
    public class Program
    {
        public static void Main()
        {
            var list = new List<ClassA>();
    
            var classB = new ClassB();
            var classC = new ClassC();
    
            list.Add(new ClassA()
            {
                blah = "Test1",
                InterfaceConcreteTypeA = classB.GetType(),
                InterfaceConcreteTypeB = classC.GetType()
            });
            list.Add(new ClassA()
            {
                blah = "Test2",
                InterfaceConcreteTypeA = classB.GetType(),
                InterfaceConcreteTypeB = classC.GetType()
            });
            list.Add(new ClassA()
            {
                blah = "Test3",
                InterfaceConcreteTypeA = classB.GetType(),
                InterfaceConcreteTypeB = classC.GetType()
            });
    
    
            XmlSerializer ser = new XmlSerializer(typeof(ClassA[]));
    
    
            using (XmlWriter writer = XmlWriter.Create("Test.xml"))
            {
                ser.Serialize(writer, list.ToArray());
            }
        }
    
        [DataContract]
        public class ClassA
        {
            [DataMember]
            public string blah { get; set; }
            [DataMember]
            public SerializableType InterfaceConcreteTypeA { get; set; }
            [DataMember]
            public SerializableType InterfaceConcreteTypeB { get; set; }
        }
        public class ClassB { }
        public class ClassC { }
    
        // a version of System.Type that can be serialized
        [DataContract]
        public class SerializableType
        {
            public Type Type;
    
            // when serializing, store as a string
            [DataMember]
            string TypeString
            {
                get
                {
                    if (Type == null)
                        return null;
                    return Type.FullName;
                }
                set
                {
                    if (value == null)
                        Type = null;
                    else
                    {
                        Type = Type.GetType(value);
                    }
                }
            }
    
            // constructors
            public SerializableType()
            {
                Type = null;
            }
            public SerializableType(Type t)
            {
                Type = t;
            }
    
            // allow SerializableType to implicitly be converted to and from System.Type
            static public implicit operator Type(SerializableType stype)
            {
                return stype.Type;
            }
            static public implicit operator SerializableType(Type t)
            {
                return new SerializableType(t);
            }
    
            // overload the == and != operators
            public static bool operator ==(SerializableType a, SerializableType b)
            {
                // If both are null, or both are same instance, return true.
                if (System.Object.ReferenceEquals(a, b))
                {
                    return true;
                }
    
                // If one is null, but not both, return false.
                if (((object)a == null) || ((object)b == null))
                {
                    return false;
                }
    
                // Return true if the fields match:
                return a.Type == b.Type;
            }
            public static bool operator !=(SerializableType a, SerializableType b)
            {
                return !(a == b);
            }
            // we don't need to overload operators between SerializableType and System.Type because we already enabled them to implicitly convert
    
            public override int GetHashCode()
            {
                return Type.GetHashCode();
            }
    
            // overload the .Equals method
            public override bool Equals(System.Object obj)
            {
                // If parameter is null return false.
                if (obj == null)
                {
                    return false;
                }
    
                // If parameter cannot be cast to SerializableType return false.
                SerializableType p = obj as SerializableType;
                if ((System.Object)p == null)
                {
                    return false;
                }
    
                // Return true if the fields match:
                return (Type == p.Type);
            }
            public bool Equals(SerializableType p)
            {
                // If parameter is null return false:
                if ((object)p == null)
                {
                    return false;
                }
    
                // Return true if the fields match:
                return (Type == p.Type);
            }
        }
    
    }
    

    编辑:我已经解决了第一个问题“System.RuntimeType由于其保护级别而无法访问”。但是现在SerializableType被序列化为空标记。查看我的更新 https://dotnetfiddle.net/ONPvDn

    1 回复  |  直到 7 年前
        1
  •  1
  •   NaDeR Star    7 年前

    您有一个名为“type”的字段,它的类型是 System.Type

    该字段仅包含对 RuntimeType 导致错误的实例。

    不可序列化。。。

    添加 [XmlIgnore]

    更新结果:

    Check it