XmlSerializer不使用由sgen创建的XmlSerializers.dll
在我的Visual Studio 2010项目中,我使用以下Post-Build事件命令行来使用sgen创建XmlSerializers.dll。
发布后事件:
"$(ProgramFiles)Microsoft SDKsWindowsv7.0ABinNETFX 4.0 Toolssgen.exe" /a:"$(TargetPath)" /c:/keyfile:"c:myprojectmykey.snk" /f
我的项目名称很强大,因此请使用相同的键来强调“XmlSerializers.dll”的名称。 VS在输出文件夹中创建XmlSerializers.dll。
但是,我注意到使用ProcessMonitor,.NET仍然在运行时调用CSC.exe。 我来到这篇文章,其中用户有类似的问题,并通过使用XmlSerializer(Type)构造函数解决。
我在我的代码中使用了相同的技术,但仍然调用csc.exe:
var fs = new FileStream(SettingsFilePath, FileMode.Open);
try
{
var serializer = new XmlSerializer(typeof(AppSettings));
settings = (AppSettings)serializer.Deserialize(fs);
}
finally
{
fs.Close();
}
我需要使用预编译的XML序列化的原因,因为性能以及我在Windows关闭时有时会看到csc.exe错误。 当窗体关闭时,我的应用程序会保存数据,在关闭期间,它会失败,因为Windows在关闭序列期间不会允许启动新流程。 我已经看到了通过预编译XML序列化来解决这个问题的建议。
有关为什么XmlSerializer不使用由sgen创建的XmlSerializers.dll的任何建议?
谢谢。
可能的问题是不同的目标平台:默认情况下, sgen
使用'任何CPU'(MSIL),如果包含要反序列化或序列化的类型的程序集编译为x86或x64,则不会加载.XmlSerializers.dll
更一般的情况是,我查看了加载序列化程序集的.NET代码 - 这里有一些代码可以重现与单元测试相同的行为:
/// <summary>Generates an identifier for the assembly of a specified type</summary>
/// <remarks>Code copied from the .NET serialization classes - to emulate the same bahavior</remarks>
/// <param name="type">The type</param>
/// <returns>String identifying the type's assembly</returns>
static string GenerateAssemblyId(Type type)
{
Module[] modules = type.Assembly.GetModules();
ArrayList list = new ArrayList();
for (int i = 0; i < modules.Length; i++) {
list.Add(modules[i].ModuleVersionId.ToString());
}
list.Sort();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.Count; i++) {
sb.Append(list[i].ToString());
sb.Append(",");
}
return sb.ToString();
} // GenerateAssemblyId
/// <summary>Verifies that the serialization assembly for the specified type can be loaded</summary>
/// <remarks>Code copied from the .NET serialization classes - to emulate the same behavior and tests</remarks>
/// <param name="type">The type</param>
static void AssertCanLoadXmlSerializers(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
Assembly serializerAssembly = null;
// Create the name of the XML serilizers assembly from the type's one
AssemblyName name = type.Assembly.GetName(true);
name.Name = name.Name + ".XmlSerializers";
name.CodeBase = null;
name.CultureInfo = CultureInfo.InvariantCulture;
try {
serializerAssembly = Assembly.Load(name);
} catch (Exception e) {
Assert.Fail("Unable to load XML serialization assembly for type '{0}': {1}", type.FullName, e.Message);
}
object[] attrs = serializerAssembly.GetCustomAttributes(typeof(XmlSerializerVersionAttribute), false);
if (attrs == null || attrs.Length == 0) {
Assert.Fail(
"Unable to use XML serialization assembly '{1}' for type '{0}': it does not contain XmlSerializerVersionAttribute",
type.FullName,
serializerAssembly.FullName
);
}
if (attrs.Length > 1) {
Assert.Fail(
"Unable to use XML serialization assembly '{1}' for type '{0}': it contains multiple XmlSerializerVersionAttribute",
type.FullName,
serializerAssembly.FullName
);
}
XmlSerializerVersionAttribute assemblyInfo = (XmlSerializerVersionAttribute)attrs[0];
string assemblyId = GenerateAssemblyId(type);
if (assemblyInfo.ParentAssemblyId != assemblyId) {
Assert.Fail(
"Unable to use XML serialization assembly '{1}' for type '{0}': it does not match assembly id '{2}'",
type.FullName,
serializerAssembly.FullName,
assemblyId
);
}
} // AssertCanLoadXmlSerializers
只需调用AssertCanLoadXmlSerializers()
传递类型,而不需要序列化/反序列化。 如果序列化程序集不加载,您可以从错误消息中获得相当好的理由。
我将它添加到我们的单元测试中,以便我可以合理确定序列化程序集是否正常。
你有没有尝试在生成的DLL上运行ngen.exe?
运行
ngen.exe install myproject.XmlSerializers.dll
将在映像缓存中安装dll的本机映像,该映像缓存应该在运行时使用,而不是调用JIT编译器。
你确定序列化程序集是否正确签名? 通常你需要避开引号。 浏览此处获取更多信息。
你也可以检查ID是否匹配。 如果在构建序列化程序集后修改源程序集,则ID不再匹配,并且不会使用序列化程序集。 浏览此处获取更多信息。
如果一切正确:禁用工具 - >选项 - >调试 - >“启用只是我的代码”并启用调试 - >强制 - >公共语言运行时异常 - >引发。 然后调试你的应用程序到串行化完成的地步。 将抛出第一个机会异常,说明为什么不能使用序列化程序集。
链接地址: http://www.djcxy.com/p/59365.html上一篇: XmlSerializer not using XmlSerializers.dll created by sgen