XmlSerializer的不使用XmlSerializers.dll由SGEN创建XmlSerializers、XmlSerializer、SGEN、dll

2023-09-04 09:01:30 作者:你是猴子派来的逗比么

在我的Visual Studio 2010的项目中,我用下面用SGEN创建XmlSerializers.dll生成后事件命令行。

In my Visual Studio 2010 project, I use following Post-Build event command line to use sgen to create 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。

My project is strong named, so use the same key to strong name the "XmlSerializers.dll". VS creates the XmlSerializers.dll in output folder.

不过,我已经使用的ProcessMonitor注意到,.NET还是调用CSC.EXE在运行时。我来到翻过这个post,其中,用户也有类似的问题,并通过使用XmlSerializer的(类型)构造解析。

However, I have noticed using ProcessMonitor, .NET still invoke CSC.exe at runtime. I came accross this post, where the user had similar issue and resolved by using XmlSerializer(Type) constructor.

我用同样的方法在我的code,但它仍然调用csc.exe的:

I used same technique in my code but it still invoke csc.exe:

var fs = new FileStream(SettingsFilePath, FileMode.Open);
try
{
var serializer = new XmlSerializer(typeof(AppSettings));
settings = (AppSettings)serializer.Deserialize(fs);
}
finally
{
fs.Close();
}

我需要使用,因为表现precompiled XML序列化的,也是我看到的Windows关机有时csc.exe的误差修改的原因。当窗体关闭,关闭期间,它失败,因为Windows将不允许一个新的进程的关机顺序期间启动我的应用程序保存数据。我见过的建议来解决这个问题由precompiling XML序列化。

The reason I need to use precompiled XML serialisation, because of performance and also I have seen sometimes csc.exe erros on Windows shutdown. My application saves data when Form close, during shutdown, it fails because Windows will not allow a new process to start during the shutdown sequence. I have seen recommendations to get around this by precompiling XML serialisation.

为什么不XmlSerializer的使用由SGEN创建XmlSerializers.dll有什么建议?

Any suggestions about why XmlSerializer not using XmlSerializers.dll created by sgen?

感谢。

推荐答案

Possiby的问题是不同的目标平台:默认情况下, SGEN 使用任何CPU(MSIL)如果要反序列化或序列化编译为86Ø64包含类型的程序集,它不会加载 .XmlSerializers.dll

Possiby the problem is different target platform: by default sgen uses 'Any CPU' (MSIL), if the assembly containing the type to be deserialized or serialized is compiled for x86 o x64, it won't load the .XmlSerializers.dll

更一般地,我有一个看.NET code表示加载序列化程序集 - 这里是一些code表示重现相同的行为作为一个单元测试:

More in general, I had a look at the .NET code that load the serialization assemblies - here is some code that reproduce the same behavior as a unit testing:

/// <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()传递的类型不是需要序列化/反序列化。如果序列化程序集不加载,你可以有,为什么从错误消息的一个相当不错的主意。

simply call AssertCanLoadXmlSerializers() passing the type than needs to be serialized/deserialized. If the serialization assemblies do not load you can have a fairly good idea of why from the error messages.

我把它添加到我们的单元测试,这样我可以确信的序列化程序集都OK了。

I added it to our unit testing, so that I can be reasonably sure that the serialization assemblies are OK.