XmlSerializer not using XmlSerializers.dll created by sgen

后端 未结 3 998
北海茫月
北海茫月 2021-01-18 06:23

In my Visual Studio 2010 project, I use following Post-Build event command line to use sgen to create XmlSerializers.dll.

Post build event:

\"$(Pro         


        
3条回答
  •  情书的邮戳
    2021-01-18 06:53

    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

    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:

    /// Generates an identifier for the assembly of a specified type
    /// Code copied from the .NET serialization classes - to emulate the same bahavior
    /// The type
    /// String identifying the type's assembly
    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
    
    /// Verifies that the serialization assembly for the specified type can be loaded
    /// Code copied from the .NET serialization classes - to emulate the same behavior and tests
    /// The type
    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
    

    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.

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

提交回复
热议问题