2012-05-09 10 views
7

В моем проекте Visual Studio 2010 я использую следующую командную строку события Post-Build, чтобы использовать sgen для создания XmlSerializers.dll.XmlSerializer не использует XmlSerializers.dll, созданный sgen

Сообщение построить событие:

"$(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-сериализации, из-за производительности, а также я видел иногда Csc.exe erros на Выключение Windows. Мое приложение сохраняет данные при закрытии формы при завершении работы, так как Windows не разрешает запуск нового процесса во время последовательности выключения. Я видел рекомендации, чтобы обойти это, предварительно скомпилировав XML-сериализацию.

Любые предложения о том, почему XmlSerializer не использует XmlSerializers.dll, созданный sgen?

Спасибо.

+0

Простейшим средством для устранения проблемы является загрузка данных при запуске. Используйте fuslogvw.exe для проверки разрешения сборки. –

+0

Спасибо, мне нужно сохранить данные (сериализовать в XML) при закрытии MainForm. При нормальном закрытии пользователем все в порядке, нет ошибки, данные сериализованы. Однако, если мое приложение работает и выключено Windows, я вижу ошибки CSC.exe. – Din

ответ

0

Вы пробовали запустить ngen.exe на сгенерированную DLL?

Запуск

ngen.exe install myproject.XmlSerializers.dll 

установит родной образ библиотеки в кэше изображения, которое должно быть использовано во время выполнения, а не ссылаться на JIT-компилятор.

+0

Спасибо, я попробовал использовать ngen.exe, но все равно вижу вызовы cse.exe в ProcessMonitor. – Din

+0

Вот скриншот ProcessMonitor: http://screencast.com/t/iyKu79yv «DataSerializer.XmlSerializers.dll» - это dll serializer, созданная sgen. – Din

4

Possiby проблема отличается целевой платформой: по умолчанию sgen использует «Any CPU» (MSIL), если узел, содержащий тип, чтобы быть десериализации или сериализованная скомпилирован для x86 x64 O, он не будет загружать .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() пропусканием типа, чем необходимо сериализовать/десериализовать. Если сборки сериализации не загружаются, вы можете неплохо понять, почему из сообщений об ошибках.

Я добавил его к нашему модульному тестированию, чтобы я мог быть уверенным, что сборки сериализации в порядке.

+0

Этот код весьма полезен. Спасибо. Я пытаюсь понять, как исправить проблему, если утверждение не выполнено на последнем блоке («оно не соответствует идентификатору сборки»). Не могли бы вы дать больше объяснений относительно того, что это значит и как это возможно сделать? –

+0

Прошло некоторое время ... идентификатор сборки состоит из номеров версий модулей в этой сборке, если они различны, это будет означать, что две сборки (одна из которых содержит тип и сериализацию) состоят из разные модули - или разные версии одних и тех же модулей - возможно, что-то изменилось после сборки сериализации? Глядя на идентификаторы, вы должны дать понять, что отличает – MiMo

+0

Спасибо - это хорошая отправная точка. –

0

Вы уверены, что сборка сериализации правильно подписана? Обычно вам нужно избегать цитат. См. here для получения дополнительной информации.

Вы также можете проверить соответствие совпадений. Если вы измените исходную сборку после сборки сборки сериализации, идентификаторы больше не совпадают, и сборка сериализации не будет использоваться. См. here для получения дополнительной информации.

Если все это правильно: отключите Инструменты -> Параметры -> Отладка -> «Включить только мой код» и включите Debug -> Excpetions -> Исключения для обычного языка Runtime -> Thrown. Затем отлаживайте приложение до точки, в которой выполняется сериализация. Первое исключение исключений будет указано, почему сборка сериализации не может быть использована.