序列化所有“新"的基类实现特性 [英] Serialize Base Class Implementation for all "new" Properties

查看:46
本文介绍了序列化所有“新"的基类实现特性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一堆从 XSD 自动生成的类,并在我没有源代码的已编译 DLL 中提供给我.我需要为每个类型添加接口,这导致了如下代码:

I have a bunch of classes that were auto-generated from an XSD, and provided to me in a compiled DLL for which I don't have the source code. I have a need to add interfaces to each of the types, which resulted in code such as the following:

public interface IBar
{
    string SomeProperty { get; set; }
}

public interface IFoo<TBar> where TBar : IBar
{
    TBar Bar { get; set; }
}

public class BarWrapper : BarFromXSD, IBar
{
}

public class FooWrapper : FooFromXSD, IFoo<BarWrapper>
{
    [XmlElement("bar")]
    public new BarWrapper Bar
    {
        get { return base.Bar as BarWrapper; }
        set { base.Bar = value; }
    }
}

如果客户端给我一个 DLL,其中任何底层类型的接口都发生了变化,我会收到编译时错误告诉我这样的信息.但是,如果底层 DLL 中的序列化属性发生更改,则情况并非如此.在这种情况下,我的包装类将很乐意序列化为与关联的 XSD 不兼容的对象.

If the client gives me a DLL where any of the interfaces to the underlying types changes, I will get compile-time errors telling me such. However, that is NOT true if the serialization attributes change in the underlying DLL. In that case, my wrapper classes will happily serialize into objects that are incompatible with the associated XSDs.

上述代码的另一个问题是它根本不起作用.当我尝试为 FooWrapper 类型的对象创建一个 XmlSerializer 时,我得到了异常链:

The other issue with the above code is that it simply doesn't work. When I try to create an XmlSerializer for objects of type FooWrapper, I get the exception chain:

反映类型MyNamespace.FooWrapper"时出现错误.
反映属性Bar"时出错.
MyNamespace.BarWrapper 类型的成员 FooWrapper.Bar 隐藏了 DLLNamespace.Bar 类型的基类成员 cs_Foo.Bar.使用 XmlElementAttribute 或 XmlAttributeAttribute 指定新名称.

There was an error reflecting type 'MyNamespace.FooWrapper'.
There was an error reflecting property 'Bar'.
Member FooWrapper.Bar of type MyNamespace.BarWrapper hides base class member cs_Foo.Bar of type DLLNamespace.Bar. Use XmlElementAttribute or XmlAttributeAttribute to specify a new name.

为了避免这个问题,我想做一个更简单的:

To avoid this issue, I would like to do the simpler of either:

1) 覆盖默认序列化,以忽略新"属性实现,或
2) 反射性地将所有 XML 序列化属性从基类复制到派生类

1) Override default serialization, in order to ignore the "new" property implementations, or
2) Reflectively copy all XML serialization attributes from the base class to the derived class

我试图用任何潜在解决方案解决的问题是:

The issues that I am trying to address with any potential solution are:

1) 我想在静态构造函数中执行一次反射,以确定序列化的元素/属性名称和命名空间.
2) 我有多个类遵循与 FooWrapper 相同的模式,所以任何解决方案都应该适用于任何此类类.
3) 遵循 FooWrapper 模式的类可以包含其他未在基类中定义的需要序列化的属性.
4) 理想的解决方案应该优雅地处理新属性.例如,如果稍后我添加或删除新"属性,则不必添加/删除其他方法,或者必须在静态构造函数中硬编码新"属性的名称.

1) I would like to perform reflection once, in the static constructor, to determine the serialized element/attribute names and namespaces.
2) I have multiple classes that follow the same pattern as FooWrapper, so any solution should would work for any such classes.
3) The classes that follow the FooWrapper pattern can contain other properties not defined in the base class that require serialization.
4) The ideal solution should gracefully handle new properties. For example, if at a later time I add or remove a "new" property, I shouldn't have to add/remove other methods, or have to hard-code the name of the "new" property in the static constructor.

非常感谢您对满足这些要求的解决方案的任何见解.

Any insight to a solution that meets these requirements is greatly appreciated.

推荐答案

这里是一个非常简单的带有继承的 xml 示例.

Here is a very simple example of xml with inheritance.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace ConsoleApplication51
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            Root root = new Root() {
                bar = new Bar1() {
                    foo = "123"
                }
            };


            XmlSerializer serializer = new XmlSerializer(typeof(Root));

            StreamWriter writer = new StreamWriter(FILENAME);
            XmlSerializerNamespaces _ns = new XmlSerializerNamespaces();
            _ns.Add("", "");
            serializer.Serialize(writer, root, _ns);
            writer.Flush();
            writer.Close();
            writer.Dispose();

        }
    }

    [XmlRoot("Root")]
    public class Root 
    {
        public Bar bar {get;set;}
    }

    [XmlInclude(typeof(Bar1))]
    [XmlRoot("Bar")]
    public class Bar 
    {
    }

    [XmlRoot("Bar1")]
    public class Bar1 : Bar
    {
        [XmlElement("foo")]
        public string foo {get;set;}
    }
}

查看 XML.添加了类型"属性.

Look at the XML. A 'type' attribute is added.

<?xml version="1.0" encoding="utf-8"?>
<Root>
  <bar d2p1:type="Bar1" xmlns:d2p1="http://www.w3.org/2001/XMLSchema-instance">
    <foo>123</foo>
  </bar>
</Root>

这篇关于序列化所有“新"的基类实现特性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆