XmlSerializer not using XmlSerializers.dll created by sgen

后端 未结 3 872
北海茫月
北海茫月 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:47

    Have you tried running ngen.exe on the generated dll?

    Running

    ngen.exe install myproject.XmlSerializers.dll
    

    will install a native image of the dll in the image cache, which should be used at runtime rather than invoking the JIT compiler.

    0 讨论(0)
  • 2021-01-18 06:52

    Are you sure that the serialization assembly is correctly signed? Usually you need to escape the quotes. See here for more information.

    You could also check if the IDs match. If you modify the source assembly after building the serialization assembly the IDs don't match any more and the serialization assembly won't be used. See here for more information.

    If all that is correct: Disable Tools -> Options -> Debugging -> "Enable Just My Code" and enable Debug -> Excpetions -> Common Language Runtime Exceptions -> Thrown. Then debug your application to the point where the serialization is done. An first chance exception will be thrown stating why the serialization assembly can't be used.

    0 讨论(0)
  • 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:

    /// <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
    

    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.

    0 讨论(0)
提交回复
热议问题