【问题标题】:Xml Deserialize to System.TypeXml 反序列化为 System.Type
【发布时间】:2018-08-21 14:54:56
【问题描述】:

我正在尝试将指定 .NET 类型的一段 XML 反序列化为 System.Type 的实例。给定

<SomeObject>
  <SomeType>System.String, mscorlib</SomeType>
</SomeObject>

反序列化为一个类;

public class SomeObject
{
    public Type SomeType { get; set; }
}

令人讨厌的是,我实际上在不久前就这样做了,但无法访问该源代码并且无法记住,事实证明,考虑到所需的关键字(“Xml”,“反序列化”),研究解决方案非常困难, "Type" 几乎提供了阳光下的一切)。

据我所知,我在SomeType 属性上放置了一个简单的AttributeXmlSerializer 从那里处理它。有谁知道我需要什么属性或者我记错了什么?

【问题讨论】:

  • 在这种情况下只需使用字符串。
  • @jdweng,如果我找不到更好的东西,我仍然可以选择,但我很确定有一个 .NET Attribute 可以用来自动处理它
  • 和这个问题类似吗? stackoverflow.com/q/6733241/2309376
  • @SimplyGed,非常接近。你知道这是否包含在专用的Attribute 中吗?

标签: c# xml xml-deserialization


【解决方案1】:

虽然我已将 Evk 的答案标记为正确(如果您要反序列化多个 Type 属性),但实际上我最终采用了一种更简单的方法。

根据this的回答,我通过SomeObject修改为;

public class SomeObject
{
    public string SomeTypeName
    {
        get { return SomeType.AssemblyQualifiedName; }
        set
        {
            var converter = new TypeNameConverter();
            SomeType = (Type)converter.ConvertFrom(value);
        }
    }

    [XmlIgnore]
    public Type SomeType { get; set; }
}

虽然单个属性的代码较短,但它不如公认的答案那么健壮。我在这里记录有两种方法可能对其他人有所帮助。

【讨论】:

    【解决方案2】:

    如果您不想拥有string 类型的附加属性(此问题的通常解决方案) - 您可以像这样使用代理类:

    public class XmlTypeProxy : IXmlSerializable {
        private string _typeName;
    
        public XmlTypeProxy() {
    
        }
    
        public XmlTypeProxy(string typeName) {
            _typeName = typeName;
        }
    
        public XmlSchema GetSchema() {
            return null;
        }
    
        public void ReadXml(XmlReader reader) {
            _typeName = reader.ReadString();
        }
    
        public void WriteXml(XmlWriter writer) {
            writer.WriteString(_typeName);
        }
    
        public static implicit operator Type(XmlTypeProxy self) {
            return Type.GetType(self._typeName);
        }
    
        public static implicit operator XmlTypeProxy(Type self) {
            return new XmlTypeProxy(self.AssemblyQualifiedName);
        }
    }
    

    这个类所做的只是将类型程序集限定名存储为字符串,并定义从Type 类型到Type 类型的隐式转换运算符。然后你只需要用XmlElement 属性装饰SomeType 并指定它的TypeXmlTypeProxy

    public class SomeObject {
        [XmlElement(Type = typeof(XmlTypeProxy))]
        public Type SomeType { get; set; }
    }
    

    现在,因为存在从 TypeXmlTypeProxy 的隐式转换(反之亦然) - 序列化和反序列化都将按您的预期工作。

    【讨论】:

    • 应该可以在没有代理类的情况下执行此操作(不过,如果我找不到任何东西,我会将其标记为已接受)。例如,在设置自定义配置部分时(当我之前这样做时),您可以将配置元素直接反序列化为 Type,而无需中间 XmlTypeProxy。在 .NET 内部的某个地方,有一种方法可以一步完成...
    • 自定义配置部分与纯 XmlSerializer 不同,其中涉及更多代码。
    • 你没有错,但我确实觉得还有办法。 “自定义配置部分”方法可以使用 [TypeConverter(typeof(TypeNameConverter))] 执行此操作,但 XmlSerializer 不使用此方法 - 链中缺少一块...
    • @DiskJunky XmlSerializer 的设计非常糟糕(至少按照现代标准)——有很多事情不能做,或者不能轻易做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多