返回首页


你可以按照这个代码@ 。简介
这是一个更新的文章和代码库从我原来的出版物[{A2}]在CodeProject。经过几年的能力和技术进步的增长,我决定是时候更新代码库和。NET 4中使用的文章。这样做的结果是一个更小的代码库,单元测试,对其进行备份,并在Web环境中发现的一些问题的修复。背景
总之,与XmlSerializer的存在,当我写的第一篇文章,今天依然存在的问题。他们是典型的问题,目前还没有统一的方法处理。主要问题仍然是序列化和反序列化时,你如何解决未知的类。
已经有多次尝试多年来,我跟着来解决这个问题,从任何地方创造的整个框架像YAXLib就如何使在复杂的各级IXmlSerializable接口的使用说明。
所有这些解决方案的主要问题,从开发商的角度来看,一直蹑手蹑脚在实施cumbersomeness。作IXmlSerializable要求开发商写一些定制化实施每类的形式。 YAXLib和其他要求开发人员使用不同的属性,或处理,​​看上去并不像由XmlSerializer的清洁(ISH)生成的XML输出​​。 [XmlInclude(类型的类型)]属性的要求,所有被序列化的类型在同一库。在我看来,他们没有(我知道)解除从单调乏味的工作与这些解决方案的开发。目标实现
序列化的额外类型的目的是尽可能盲目发展的考虑绝对最低。它的作用是利用标准XmlSerializer的略有联合国的重载的构造,它已纳入序列化和反序列化类型的决议的过程中使用的额外的类型定义。
它实际上是一个非常简单的想法。保持XmlSerializer的可能有需要在一个序列化/反序列化过程中的所有可能的类型的列表。注册类型,使用属性装饰,并提供了一​​些扩展的方法,使纳入那些盲目开发的名单。
它的工作原理下的父子关系。我最能形容说,它的反向XmlInclude属性。 XmlInclude属性被放置在一个类,给其他类的序列化程序序列化的装饰类知识。 SerializableExtraType是放在一类,装饰类,其他类是序列化时的其他类知识。
所以... ...

XmlInclude = Parent => Child

SerializableExtraType = Child => Parent

SerializableExtraTypes代码允许跨库集成相关的类。此外,我已经暴露的方法是,你可以注册在运行时的额外的关系。这解决了任何情况下,你可能会与库和复杂的隐含关系的应用跨越。使用代码
代码是在下载并在CodePlex站点。两者有一系列的测试库和一个耗时的测试项目非常好,显示用法。在这里,我将概述如何利用它的快速和肮脏的。
首先,装饰一类需要这样的属性:{C}
扩展方法下的System.Xml.Serialization使用SerializableExtraTypes。
现在使用扩展​​方法来序列化和反序列化对象。
// example 1 assuming that ClassOne and ClassTwo inherit from Foo

string xml = new Foo { ClassList = {new ClassOne(), new ClassTwo(), }, }.SerializeEx();

Foo obj = "<Foo><ClassList><ClassOne /><ClassTwo /></Foo>".DeserializeEx<Foo>();



// example 2 assuming that Foo bears no relationship with SomethingElse

string xml = new SomethingElse { ObjectList = { new Foo(), new Foo(), }, }.SerializeEx();

SomethingElse obj = "<SomethingElse><ArrayOfObject><Foo />" + 

   "<Foo /></ArrayOfObject></SomethingElse>".DeserializeEx<SomethingElse>();

有更多的功能,内置的代码库,但这是一个快速和肮脏的样本。请看看在作进一步的例子下载。历史{A3}。2011年5月,24日:第二份出版物的第一稿。
这是这种方法的第二份出版物。请发送任何意见或建议如何改进它。您可以通过电子邮件我在{A4}。

回答

评论会员:丹尼尔Gidman 时间:2012/01/27
因为你的属性将始终以创建一个数组(类型),
你还不如改变构造函数允许传递数组。

public class SerializableExtraTypeAttribute : Attribute

{

    /// <summary>

    /// Initializes a new instance of the <see cref="SerializableExtraTypeAttribute"/> class.

    /// </summary>

    /// <param name="types">The types.</param>

    public SerializableExtraTypeAttribute(params Type[] types)

        : base()

    {

        _Types = types;

    }

 

    private IEnumerable<Type> _Types = null;

 

    /// <summary>

    /// Gets the types.

    /// </summary>

    public IEnumerable<Type> Types

    {

        get { return _Types; }

    }

}

这种方式,您将只需要一个构造,可以使用尽可能多的类型,你想要
:丹尼尔Gidman
评论会员:游客 时间:2012/01/27
不工作由于它是一个属性。IDE和编译器的属性的构造排除的params力量。基本上抛出一个错误。不过,我认为实际的数组来解决这个问题的建设者之一
鲍勃桑德伯格
评论会员:游客 时间:2012/01/27
我的工作与VS2010一切,和它工作正常,我的机器上我不工作可设计类,这样就可能是
丹尼尔Gidman
评论会员:游客 时间:2012/01/27
。尼斯,以及属性的变化必须已经进入NET4中,因为不允许NET2,感谢您的更新。我也建议把周围的一个小错误的预期。codeprelang="c#"spanclass="code-keyword"public/spanSerializableExtraTypeAttribute(spanclass="code-keyword"params/spanType[]types):spanclass="code-keyword"base/span(){_Types=types.Where(t=>t!=spanclass="code-keyword"null/span).ToArray();}/pre/code这种变化,我已经更新在CodePlex库
。BillWoodruff
评论会员:游客 时间:2012/01/27
codeprelang="c#"/pre/code嘿,序列化过程中突然可以访问私有构造函数在DOTNET2.0TimeSpan类是不可序列化,因为它有一个私人(paramterless)构造。这意味着你不能使用一个WebService,或在DataSet。现在,4.0,你的TimeSpan类型的列时,您的SQL列类型的时间是因此,他们固定在序列化过程中的一些东西(那么你可能会问,他们不解决这个问题....){BR}这是伟大的,因为你现在可以生成序列化的对象必须初始化:codeprelang="c#"spanclass="code-keyword"public/spanspanclass="code-keyword"class/spanDemo{spanclass="code-keyword"string/span_ThisHasToHaveAValue; spanclass="code-keyword"public/spanspanclass="code-keyword"string/spanThisHasToHaveAValue{spanclass="code-keyword"get/span{spanclass="code-keyword"return/span_ThisHasToHaveAValue;}spanclass="code-keyword"set/span{spanclass="code-comment"///spanspanclass="code-comment"ensurevalue./spanspanclass="code-keyword"if/span(spanclass="code-keyword"string/span.IsNullOrEmpty(value)spanclass="code-keyword"throw/spanspanclass="code-keyword"new/spanInvalidOperationException(spanclass="code-string""/spanspanclass="code-string"nono"/span);_ThisHasToHaveAValue=value;}} spanclass="code-keyword"private/spanspanclass="code-keyword"void/spanDemo(){spanclass="code-comment"///spanspanclass="code-comment"hideconstructor./span}spanclass="code-keyword"public/spanspanclass="code-keyword"void/spanDemo(spanclass="code-keyword"string/spanvalue){ThisHasToHaveAValue=value;}}/pre/code
丹尼尔Gidman
评论会员:游客 时间:2012/01/27
丹尼尔,我挣扎着这个问题,很长一段时间。尽一切,你写一个好看的扩展库。建设类是来自通过XML封送处理库,这是一个重大的痛苦。我想给这个尝试,但我下载并尝试运行测试,我得到这个错误。任何想法?测试"SerializableExtraTypes.Tests.SerializableExtensionMethodsTest.SerializeExTest'失败:测试方法SerializableExtraTypes.Tests.SerializableExtensionMethodsTest.SerializeExTest抛出异常:System.TypeInitializationException:'Net.AMightyOak.SerializableExtraTypes"的类型初始抛出一个异常。---System.Reflection.ReflectionTypeLoadException:无法加载一个或多个请求的类型。检索更多信息LoaderExceptions财产。在System.Reflection.RuntimeModule.GetTypes(RuntimeModule模块)在System.Reflection.RuntimeModule.GetTypes()在System.Reflection.Assembly.GetTypes()SerializableExtraTypes.cs(91,0):在Net.AMightyOak.SerializableExtraTypes.d__1f.MoveNext()SerializableExtraTypes.cs(30,0):..Net.AMightyOak.SerializableExtraTypesCTOR()SerializableExtraTypes.cs(105,0):..Net.AMightyOak.SerializableExtraTypescctor()---结束内部异常堆栈跟踪---在Net.AMightyOak.SerializableExtraTypes.GetTypes(类型为type)鲍勃桑德伯格
丹尼尔Gidman
评论会员:游客 时间:2012/01/27
1)你有没有NET4中加载。(我知道愚蠢的问题)2)尝试运行它从一个从CodePlex项目@{A5}最新*知道也有一个较旧的。NET3.5解决方案,以及除此之外,它可能是配置问题或东西。我跑在调试就好。"无法加载"请求的类型,以及可能是一个坏的项目引用,这是第一推回约80下载或所以说,任何关于错误的,而我不想贬谪到"就在你身边"这也许真的是
。萨沙理发
评论会员:游客 时间:2012/01/27
优秀的技术写作!感谢。最好的是,条例草案"的原因是自然秩序的真理,但想象力是器​​官意思是"CS刘易斯
。丹尼尔Gidman
评论会员:感谢条例草案" 时间:2012/01/27
萨沙理发
评论会员:游客 时间:2012/01/27
!出色的工作感谢分享。{S0}|丹尼尔Gidman
评论会员:萨沙理发 时间:2012/01/27
与WCF,我们的工作很多,使用{A6}]和那些我可以像
的东西

[DataContract]

public Class1

{

   [DataMember]

   public Class2 { get; set; }

}
和序列化Class1的就好了,它会知道怎么也序列化Class2的就好了。 是你的问题在​​XML序列化的目的?萨沙理发
微软的Visual C#MVP 2008年2011Codeproject MVP 2008 - 2011Open源码
{A7}
你最好的朋友就是你。我是我最好的朋友。我们有着共同的看法,并未落认为

我的博客:{A8}
评论会员:约翰Kasra 时间:2012/01/27
XmlSerializer的处理,只是罚款。更改的公式了。


public abstract class Class1 { }

public class Class2 : Class1 { }

public class Class3 : Class1 { }

public class Class4 : Class2 { }

 

[SerializableExtraType(typeof(Class1))]

public class SomethingElse

{

  public List<Class1> ListOfClasses { get; set; }

}



SomethingElse obj = new SomethingElse { ListOfClasses = new List<Class1> { new Class2(), new Class3(), new Class4(), }, };

 

string xml = obj.SerializeEx();

SomethingElse obj2 = xml.DeserialzieEx<SomethingElse>();


尝试做一个XmlSerializer,将炸弹,因为Class1是抽象的,有没有其子类型的知识。
我不认为DataSerializer将处理,要么
评论会员:。丹尼尔Gidman 时间:2012/01/27
再次我可能失去了一些东西,但我可以使用{A9}

[KnownType(typeof(Class2)]

[KnownType(typeof(Class3)]

[KnownType(typeof(Class4)]

public abstract class Class1 { }

 

[KnownType(typeof(Class4)]

public class Class2 : Class1 { }

 

public class Class3 : Class1 { }

 

public class Class4 : Class2 { }


在那里我有东西像

[DataContract]

public SomeOtherClass

{

  [DataMember]

  public Class2 MyClass2 {get; set;}

 

  [DataMember]

  public Class3 MyClass3 {get; set;} 

 

  [DataMember]

  public Class4 MyClass4 {get; set;}

 

}
我也有你的例子太
public class SomethingElse

{

  public List<Class1> ListOfClasses { get; set; }

}

 



SomethingElse obj = new SomethingElse { ListOfClasses = new List<Class1> { new Class2(), new Class3(), new Class4() }, };
就像我说我可能失去了一些东西,但我认为这是什么{A9}]大约
萨沙理发
微软的Visual C#MVP 2008年2011Codeproject MVP 2008 - 2011Open源码
{A7}
你最好的朋友就是你。我是我最好的朋友。我们有着共同的看法,并未落认为

我的博客:{A8}
评论会员:Jefis 时间:2012/01/27
。如果KnownType像XmlInclude的东西,然后它仅适用于在同一库或直接引用库,你必须访问类被序列化
这可以跨库序列化的类,你是你有没有访问,不能身体装饰与KnownType或XmlInclude。
你的例子,假设您有充分的机会和控制,我没有这样的假设。

当然,我不会走出去,并声称,DataContract不会处理所有这些问题,在这种或那种形式,因为我不知道,但这种解决方案的目的是在XmlSerializer的
评论会员:。 时间:2012/01/27