在我的 Visual Studio 2010 项目中,我使用以下 Post-Build 事件命令行来使用 sgen 创建 XmlSerializers.dll。
构建后事件:
"$(ProgramFiles)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\sgen.exe" /a:"$(TargetPath)" /c:/keyfile:"c:\myproject\mykey.snk" /f
我的项目是强命名的,因此使用相同的密钥对“XmlSerializers.dll”进行强命名。 VS 在输出文件夹中创建 XmlSerializers.dll。
但是,我注意到使用 ProcessMonitor,.NET 仍然在运行时调用 CSC.exe。我遇到过这个post,其中用户遇到类似问题并通过使用 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 有什么建议吗?
Thanks.
问题可能是不同的目标平台:默认情况下sgen
使用“任何 CPU”(MSIL),如果包含要反序列化或序列化的类型的程序集是为 x86 o 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()
传递需要序列化/反序列化的类型。如果序列化程序集未加载,您可以从错误消息中很好地了解原因。
我将其添加到我们的单元测试中,以便我可以合理地确定序列化程序集没问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)