在 IIS/ASP.NET 中具有继承类型的 XmlSerializer 序列化错误,但在桌面 .NET 应用程序中没有



我问这个问题主要是为了记录一个我花了几个小时来解决的问题,我在网上找不到解决方案。

我正在使用 XmlSerializer 来序列化和反序列化基类,其中有几个继承的类:

public abstract class WorkRequest
{}
[WorkRequest]
public class A : WorkRequest
{}
[WorkRequest]
public class B : WorkRequest
{}

派生类的类型通过反射加载。 关键点是如何查找和加载 DLL 的引用:

string path;
Assembly main = Assembly.GetEntryAssembly();
if (main == null) // IIS 
path = AppDomain.CurrentDomain.RelativeSearchPath;
else // Standard .NET Service
{
path = main.Location;
path = path.Substring(0, path.LastIndexOf(Path.DirectorySeparatorChar));
}
string[] fileList = Directory.GetFiles(path, "*.dll");
if (main != null)
RegisterInterfaces(main);
foreach (string file in fileList)
{
try
{
Assembly asm = Assembly.LoadFile(file);
RegisterInterfaces(asm);
}
catch (Exception e)
{
}
}

当应用程序在 asp.net 中运行时,AppDomain.CurrentDomain.RelativeSearchPath 返回 IIS 中 Web 应用程序的 bin 目录。 作为标准 .NET 服务运行时,条目程序集位置用于加载引用的程序集以查找请求类型。 DLL 中的类使用 WorkRequestAttribute 探测所有类型的类。

序列化按如下方式完成:

var settings = new XmlWriterSettings()
{
//Encoding = Encoding.UTF8,
Indent = false,
OmitXmlDeclaration = true
};
using (var tw = new StringWriter())
using (var xmlWriter = XmlWriter.Create(tw, settings))
{
var serializer = GetSerializer(typeof(WorkRequest));
serializer.Serialize(xmlWriter, input);
tw.Flush();
return tw.ToString();
}

序列化程序按如下方式加载:

var serializer = new XmlSerializer(theType, _knownTypes.Value);

建议使用序列化程序分配一次并缓存,类型为 typeof(WorkRequest)。 _knownTypes是从工作请求继承的类,这些类是通过上述代码使用 WorkRequest 属性进行反射找到的。

此代码作为 .NET 服务运行良好,引用的类型加载如上所示。 在 IIS 中运行时,当调用 XmlSerializer.Serialize() 函数时,报告了以下异常:

类型 A 是意料之外的。使用 xmlInclude 或 SoapInclude 属性来指定静态未知的类型。

我还尝试对继承的类型 A 和相同的已知类型列表使用序列化程序,但报告了以下错误:

类型 A' 和 "A" 都使用 XML 类型名称"MyClass",来自命名空间"。使用 XML 属性可以 为类型指定唯一的 XML 名称和/或命名空间。

IIS 应用程序加载 DLL 的方式似乎与我加载它们的方式不同,并且已知类型不匹配,序列化程序找不到该类型。 是否有任何建议我在 IIS 中运行时加载类型做错了什么?

有没有其他方法可以解决这个问题来解决问题?

我通过使用传入的请求类型作为显式已知类型并且仍然使用typeof(WorkRequest)的序列化程序来解决问题。 对已知类型的引用是正确的。 请注意,这并不能解决 IIS 中的反序列化问题,但目前我不需要这样做。

似乎核心问题是在 .NET 中加载程序集,这些类型,即使它们是相同的,.NET 也不认为它们是相同的类型,并且没有使用加载的已知类型。

相关内容

最新更新