为所有" new"序列化基类实现属性

时间:2015-09-21 16:37:46

标签: c# serialization reflection xml-serialization

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

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不兼容的对象。

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

  

有一个错误反映出类型&#39; MyNamespace.FooWrapper&#39;   有一个错误反映了财产&#39; Bar&#39;   MyNamespace.BarWrapper类型的成员FooWrapper.Bar隐藏DLLNamespace.Bar类型的基类成员cs_Foo.Bar。使用XmlElementAttribute或XmlAttributeAttribute指定新名称。

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

  

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

我试图用任何可能的解决方案解决的问题是:

  

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

非常感谢对符合这些要求的解决方案的任何见解。

1 个答案:

答案 0 :(得分:0)

这是一个带继承的xml的简单示例。

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。 A&#39;类型&#39;属性已添加。

<?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>