加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – XmlSerializer不使用sgen创建的XmlSerializers.dll

发布时间:2020-12-15 07:40:27 所属栏目:百科 来源:网络整理
导读:在我的Visual Studio 2010项目中,我使用以下Post-Build事件命令行来使用sgen来创建XmlSerializers.dll. 发布后事件: "$(ProgramFiles)Microsoft SDKsWindowsv7.0ABinNETFX 4.0 Toolssgen.exe" /a:"$(TargetPath)" /c:/keyfile:"c:myprojectmykey.sn
在我的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.我来到这个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的任何建议?

谢谢.

解决方法

Possiby问题是不同的目标平台:默认情况下sgen使用’Any 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",serializerAssembly.FullName
    );
  }
  if (attrs.Length > 1) {
    Assert.Fail(
      "Unable to use XML serialization assembly '{1}' for type '{0}': it contains multiple XmlSerializerVersionAttribute",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}'",serializerAssembly.FullName,assemblyId
    );
  }
} // AssertCanLoadXmlSerializers

只需调用AssertCanLoadXmlSerializers()传递类型,而不是需要序列化/反序列化.如果序列化程序集没有加载,您可以从错误消息中很好地了解原因.

我将它添加到我们的单元测试中,以便我可以合理地确定序列化程序集正常.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读