XmlSerializer在使用泛型类型约束时抛出InvalidOperationException异常

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

ClassLibrary.cs

public interface ITest
{
}

Program.cs

using System;

public class TestClass
{
    public void Test<T>(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。

at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence)
at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies) at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence) at System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping, Type type, String defaultNamespace) at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace) at Program.Main(String[] args)

TestClass中删除where T : ITest 或者根本不使用泛型(例如使用public void Test(ITest x))将防止抛出异常,但我需要在我的实际应用程序中使用这种构造。

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


随机猜测:您的GAC中是否有ClassLibrary的旧版本? - Jimmy
@Jimmy:不行——因为这个问题对我来说看起来非常奇怪,所以我设置了一个全新的文件集,并只使用csc.exe进行编译。更改ClassLibrary.cs的名称并没有任何帮助。 - Martin
3个回答

6

我认为你运气不佳。以下是微软的回复:

感谢您提交此问题。很遗憾,我们决定不予解决,因为修复的风险大于其收益。到下一次改变的机会出现时,希望未来版本的Windows Communication Foundation中的新序列化技术能够解决您的情况。如果此问题对业务造成了重大负面影响,请联系Microsoft产品支持服务。我们很遗憾无法提供更好的解决方案。请放心,我们认真考虑了此问题-“不修复”决策从未轻易做出。

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


3
实际上,您也许已经非常接近解决问题了,而且可能还不知道。
请尝试在您的ClassLibrary程序集中定义一个空的辅助类,并将[Serializable, XmlInclude(SerializationReferenceHelper)]放置在public class TestClass之前。
问题在于Xml解析器不知道第二个类的存在,因为它在另一个程序集中,并且仅被代码中的where约束所引用。是的,Microsoft可以编写一段小程序来查找所有已知程序集……不确定他们为什么不这样做。但是现在这个方法或许可行。

ClassLibrary

public class SerializationReferenceHelper { }
public interface ITest { }

程序

[Serializable, XmlInclude(typeof(SerializationReferenceHelper))]
public class TestClass
{
    public void Test<T>(T x) where T : ITest { }
}

static class Program
{ 
    static void Main(string[] args)         
    {
        new System.Xml.Serialization.XmlSerializer(typeof(TestClass));
    }
}

-3
类型 ITest 是在一个未被引用的程序集中定义的。您必须添加对 ClassLibrary 程序集的引用。你做到了吗?

看看我执行的命令-参数/reference:ClassLibrary.dll 就是在做这件事。 - Martin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接