当使用generics类型约束时,XmlSerializer抛出InvalidOperationException

当我尝试运行以下代码(两个分离的程序集)时

ClassLibrary.cs

public interface ITest { } 

Program.cs中

 using System; public class TestClass { public void Test(T x) where T : ITest { } } static class Program { static void Main(string[] args) { new System.Xml.Serialization.XmlSerializer(typeof(TestClass)); } } 

使用以下命令在Windows 7 64位中编译:

c:\ Windows \ Microsoft.NET \ Framework \ v2.0.50727 \ csc / target:library ClassLibrary.cs

c:\ Windows \ Microsoft.NET \ Framework \ v2.0.50727 \ csc /reference:ClassLibrary.dll Program.cs

我得到了这个例外:

System.InvalidOperationException:无法生成临时类(result = 1)。 错误CS0012:类型ITest在未引用的程序集中定义。 您必须添加对程序集ClassLibrary的引用,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null hinzu。

在System.Xml.Serialization.Compiler.Compile(Assembly parent,String ns,XmlSerializerCompilerParameters xmlParameters,Evidence evidence)
在System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping [] xmlMappings,Type [] types,String defaultNamespace,Evidence evidence,XmlSerializerCompilerParameters参数,Assembly assembly,Hashtable程序集)System.Xml.Serialization.TempAssembly..ctor(XmlMapping [ ] System.Xml.Serialization.XmlSerializer..ctor处的System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping,Type type,String defaultNamespace)中的xmlMappings,Type [] types,String defaultNamespace,String location,Evidence evidence)(Type Program.Main(String [] args)中的type,String defaultNamespace)

TestClass中移除where T:ITest或者根本不使用generics(例如使用public void Test(ITest x) )将防止抛出exception,但我需要在我的实际应用程序中使用此构造。

有人理解为什么XmlSerializer无法处理where约束吗?

我觉得你运气不好 。 以下是Microsoft对此问题的回复:

感谢您提交此问题。 不幸的是,我们已经决定不解决它,因为修复的风险超过了它的好处。 当下一次实现此更改的机会出现时,希望未来版本的Windows Communication Foundation中的新序列化技术能够满足您的需求。 如果此问题导致严重的负面业务影响,请与Microsoft产品支持服务联系。 我很遗憾无法提供更好的解决方案。 请放心,我们认真考虑了这个问题 – 一个不会修复的决定从来都不容易。

这基本上说你应该使用DataContractSerializer而不是XmlSerializer或更改你的对象结构。

实际上,你可能非常接近,甚至不知道。

尝试在ClassLibrary程序集中定义一个空的帮助器类,并将[Serializable, XmlInclude(SerializationReferenceHelper)]放在public class TestClass之上。

问题是Xml解析器不知道第二个类,因为它位于不同的程序集中,并且仅由代码中的where约束引用。 是的,微软可能会写一些小曲目来查看所有已知的程序集……不确定它们为什么不这样做。 但是现在这可能会奏效。

ClassLibrary

 public class SerializationReferenceHelper { } public interface ITest { } 

程序

 [Serializable, XmlInclude(typeof(SerializationReferenceHelper))] public class TestClass { public void Test(T x) where T : ITest { } } static class Program { static void Main(string[] args) { new System.Xml.Serialization.XmlSerializer(typeof(TestClass)); } } 

ITest类型在未引用的程序集中定义。 您必须添加对程序集ClassLibrary的引用

你做过这个吗?