Создание сборки сериализации XML как часть моей сборки

Этот код создает исключение FileNotFoundException, но в конечном итоге выполняется без проблем:

void ReadXml()
{
    XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
    //...
}

Вот исключение:


Первое случайное исключение типа System.IO.FileNotFoundException произошло в mscorlib.dll

Дополнительная информация: не удалось загрузить файл или сборку MyAssembly.XmlSerializers, Version = 1.4.3190.15950, Culture = нейтральный, PublicKeyToken = null или одну из их зависимостей. Система не может найти указанный файл.


Похоже, что платформа автоматически генерирует сборку сериализации, если она не найдена. Я могу сгенерировать его вручную с помощью sgen.exe, что устраняет исключение.

Как заставить Visual Studio автоматически генерировать сборку сериализации XML?


Обновление: параметр «Создать сборку сериализации: при включении», похоже, ничего не делает.

Я также решил использовать Sgen, который работает для обычных типов. Однако это не позволяет мне создавать экземпляры XmlSerializer для массивов этих типов. Если вы столкнулись с этим, напишите здесь: stackoverflow.com/questions/1844870/…

anthony 04.12.2009 22:47
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
66
1
62 992
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Посмотрите свойства решения. На вкладке сборки внизу есть раскрывающийся список под названием «Создать сборку сериализации».

Похоже, это ничего не дает.

Adam Tegen 25.09.2008 20:23

вы должны переключить его на «Вкл.». Авто, похоже, ничего не делает

Darren Kopp 25.09.2008 21:23

ничего не производит, даже если установлено на ON

sarsnake 09.09.2009 00:46

который работает только для типов прокси веб-служб - в противном случае следует использовать задачу MSBuild <SGen /> (или командный инструмент sgen.exe).

ProfyTroll 29.12.2010 16:56

Открыта проблема с MS Connect, которая означает, что она была закрыта по причине "По замыслу" connect.microsoft.com/VisualStudio/feedback/details/123088/…

Daniel McQuiston 21.03.2012 01:34
Ответ принят как подходящий

Вот как мне удалось это сделать, изменив сценарий MSBUILD в моем файле .CSPROJ:

Сначала откройте файл .CSPROJ как файл, а не как проект. Прокрутите файл до конца, пока не найдете закомментированный код непосредственно перед закрытием тега Project:

<!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name = "BeforeBuild">
</Target>
<Target Name = "AfterBuild">
</Target>
-->

Теперь мы просто вставляем нашу собственную цель AfterBuild, чтобы удалить любой существующий XmlSerializer, а SGen - наш собственный, например:

<Target Name = "AfterBuild" DependsOnTargets = "AssignTargetPaths;Compile;ResolveKeySource" Inputs = "$(MSBuildAllProjects);@(IntermediateAssembly)" Outputs = "$(OutputPath)$(_SGenDllName)">
   <!-- Delete the file because I can't figure out how to force the SGen task. -->
   <Delete
     Files = "$(TargetDir)$(TargetName).XmlSerializers.dll"
     ContinueOnError = "true" />
   <SGen
     BuildAssemblyName = "$(TargetFileName)"
     BuildAssemblyPath = "$(OutputPath)"
     References = "@(ReferencePath)"
     ShouldGenerateSerializer = "true"
     UseProxyTypes = "false"
     KeyContainer = "$(KeyContainerName)"
     KeyFile = "$(KeyOriginatorFile)"
     DelaySign = "$(DelaySign)"
     ToolPath = "$(TargetFrameworkSDKToolsDirectory)"
     Platform = "$(Platform)">
      <Output
       TaskParameter = "SerializationAssembly"
       ItemName = "SerializationAssembly" />
   </SGen>
</Target>

Это подходит для меня.

Спасибо, отлично поработали. Помогло то, что я поместил классы, которые мне нужно было сериализовать, в отдельный проект, чтобы SGEN просто работал с ними.

Craig Shearer 03.12.2009 00:08

Не забудьте включить платформу для SGen, если делаете сборки для конкретной платформы, например: Platform = "$ (Platform)". Я получал ошибку вроде: WRN: сравнение имени сборки привело к несоответствию архитектуры процессора: Ref x86, Def MSIL.

Scott 02.02.2011 05:28

Это прекрасно генерирует файлы DLL, но, похоже, все еще производит генерацию сборки на лету. Нужно ли мне что-то делать с этой DLL после ее создания?

RandomEngy 18.07.2011 08:29

Просто разверните его. Вы можете использовать отладчик, чтобы точно узнать, какой тип вызывает создание динамической сборки. Даже если вы сериализуете все свои типы, они наверняка состоят из других типов, некоторых типов фреймворка, которые могут потребовать создания сборки.

flipdoubt 18.07.2011 15:33

Это происходит в .DLL, где определены классы, или в проекте для .exe? Я полагаю, поскольку это MSBuildAllProjects, он правильно помещается в .exe?

Seph 07.11.2011 10:07

В других ответах на этот вопрос уже упоминался параметр Project Properties-> Build-> Создание сборок сериализации, но по умолчанию он будет генерировать сборку только в том случае, если в проекте есть «Типы прокси веб-службы XML».

Лучший способ понять точное поведение Visual Studio - изучить цель GenerateSerializationAssemblies в файле C: \ WINDOWS \ Microsoft.NET \ Framework \ v2.0.50727 ** Microsoft.Common.targets **.

Вы можете проверить результат этой задачи сборки в окне Visual Studio Выход и выбрать Строить в раскрывающемся списке Показать вывод из :. Вы должны увидеть что-то вроде

C: \ Program Files \ Microsoft Visual Studio 8 \ SDK \ v2.0 \ bin \ sgen.exe /assembly:D:\Temp\LibraryA\obj\Debug\LibraryA.dll / прокси-типы / ссылка: .. / компилятор: / задержка LibraryA -> D: \ Temp \ LibraryA \ bin \ Debug \ LibraryA.dll

Ключевым моментом здесь является переключатель / прокси-типы. Вы можете прочитать о различных переключателях для Инструмент создания XML-сериализатора (Sgen.exe)

Если вы знакомы с MSBuild, вы можете настроить цель GenerateSerializationAssemblies так, чтобы задача SGen имела атрибут UseProxyTypes = "false" вместо true, но тогда вам необходимо взять на себя всю связанную с этим ответственность по настройке системы Visual Studio / MSBuild. В качестве альтернативы вы можете просто расширить процесс сборки, чтобы вызвать SGen вручную без переключателя / proxytypes.

Если вы читаете документацию по SGen, они довольно ясно понимают, что Microsoft хотела ограничить использование этой возможности. Учитывая количество шума по этой теме, совершенно очевидно, что Microsoft не очень хорошо справилась с документированием опыта Visual Studio. Для этой проблемы есть даже элемент Подключить обратную связь, и ответ невысокий.

На случай, если кто-то еще столкнется с этой проблемой внезапно после того, как все работало нормально раньше: для меня это было связано с тем, что флажок «Включить только мой код (только управляемый)» был снят в меню параметров (Параметры -> Отладка) (который был автоматически выключается после установки .NET Reflector).

Обновлено: Это, конечно, означает, что это исключение происходило раньше, но когда параметр «Включить только мой код» отключен, помощник по отладке (если он включен) остановится на этом этапе при вызове.

Как объяснил Мартин в его ответ, включения генерации сборки сериализации через свойства проекта недостаточно, потому что задача SGen добавляет переключатель /proxytypes в командную строку sgen.exe.

У Microsoft есть задокументированное свойство MSBuild, который позволяет отключить переключатель /proxytypes и заставляет задачу SGen генерировать сборки сериализации, даже если в сборке нет типов прокси.

SGenUseProxyTypes

A boolean value that indicates whether proxy types should be generated by SGen.exe. The SGen target uses this property to set the UseProxyTypes flag. This property defaults to true, and there is no UI to change this. To generate the serialization assembly for non-webservice types, add this property to the project file and set it to false before importing the Microsoft.Common.Targets or the C#/VB.targets

Как указано в документации, вы должны изменить файл проекта вручную, но вы можете добавить свойство SGenUseProxyTypes в свою конфигурацию, чтобы включить генерацию. Конфигурация файлов вашего проекта будет выглядеть примерно так:

  <PropertyGroup Condition = " '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <!-- Snip... -->
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
    <SGenUseProxyTypes>false</SGenUseProxyTypes>
  </PropertyGroup>
  <PropertyGroup Condition = " '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <!-- Snip... -->
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
    <SGenUseProxyTypes>false</SGenUseProxyTypes>
  </PropertyGroup>

(+1) Первоначально я начал путь к выбранному ответу, но обнаружил (по крайней мере, в MSBuild 4.0), что сработала только установка свойства $ (SGenUseProxyTypes), исправление одной строки!

Brian Kretzler 29.03.2012 00:06

Я протестировал и подтвердил, что это работает в Visual Studio 2008. Большое спасибо за то, что откопали это.

Pete Magsig 04.05.2013 06:41

Согласовано! Отличный ответ

Chris 08.01.2014 02:14

Мне не хватало этой части, наконец-то удалось решить эту проблему. Очень полезный ответ!

Michel van Engelen 04.05.2017 11:15

Я попробовал это, и он сгенерировал 32-битный XmlSerializers.dll, хотя мой проект настроен для x64. Есть ли параметр "разрядности" для XmlSerializers?

Paul McCarthy 04.05.2017 12:17

создание нового определения задачи sgen ломает муху на лету. просто установите необходимые переменные, чтобы задача работала должным образом. В любом случае в документации Microsoft отсутствует важная информация.

Шаги по предварительному созданию сборок сериализации

(с деталями из http://msdn.microsoft.com/en-us/library/ff798449.aspx)

  1. В Visual Studio 2010 в обозревателе решений щелкните правой кнопкой мыши проект, для которого вы хотите создать сборки сериализации, и выберите команду «Выгрузить проект».
  2. В обозревателе решений щелкните правой кнопкой мыши проект, для которого вы хотите создать сборки сериализации, и выберите команду Изменить .csproj.
  3. В файле .csproj сразу после элемента <TargetFrameworkVersion>v?.?</TargetFrameworkVersion> добавьте следующие элементы:

    <SGenUseProxyTypes>false</SGenUseProxyTypes><SGenPlatformTarget>$(Platform)</SGenPlatformTarget>

  4. В файле .csproj в каждой конфигурации платформы

    например <PropertyGroup Condition = "'$(Configuration)|$(Platform)' == 'Debug|x86'">

    добавьте следующую строку:

    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>

  5. Сохраните и закройте файл .csproj.

  6. В обозревателе решений щелкните правой кнопкой мыши только что отредактированный проект и выберите "Перезагрузить проект".

Эта процедура создает дополнительную сборку с именем .xmlSerializers.dll в выходной папке. Вам нужно будет развернуть эту сборку с вашим решением.


Объяснение

SGen по умолчанию только для типов прокси генерирует для «Any CPU». Это произойдет, если вы не установите соответствующие переменные в файле проекта.

SGenPlatformTarget требуется для соответствия вашему PlatformTarget. Я склонен думать, что это ошибка в шаблоне проекта. Почему целевая платформа sgen должна отличаться от платформы вашего проекта? Если это так, вы получите исключение времени выполнения

0x80131040: The located assembly's manifest definition does not match the assembly reference

Вы можете найти определение задачи msbuild, проанализировав файл проекта:

<Import Project = "$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

где MSBuildToolsPath зависит от вашего <TargetFrameworkVersion>http://msdn.microsoft.com/en-us/library/bb397428.aspx

Загляните внутрь определения задачи SGen для TargetFrameworkVersion 4.0 из

Windows installation path\Microsoft.NET\Framework\v4.0.30319\Microsoft.CSharp.targets

чтобы увидеть недокументированные переменные, такие как $ (SGenPlatformTarget), которые вы можете установить в файле проекта

<Target
    Name = "GenerateSerializationAssemblies"
    Condition = "'$(_SGenGenerateSerializationAssembliesConfig)' == 'On' or ('@(WebReferenceUrl)'!='' and '$(_SGenGenerateSerializationAssembliesConfig)' == 'Auto')"
    DependsOnTargets = "AssignTargetPaths;Compile;ResolveKeySource"
    Inputs = "$(MSBuildAllProjects);@(IntermediateAssembly)"
    Outputs = "$(IntermediateOutputPath)$(_SGenDllName)">

    <SGen
        BuildAssemblyName = "$(TargetFileName)"
        BuildAssemblyPath = "$(IntermediateOutputPath)"
        References = "@(ReferencePath)"
        ShouldGenerateSerializer = "$(SGenShouldGenerateSerializer)"
        UseProxyTypes = "$(SGenUseProxyTypes)"
        KeyContainer = "$(KeyContainerName)"
        KeyFile = "$(KeyOriginatorFile)"
        DelaySign = "$(DelaySign)"
        ToolPath = "$(SGenToolPath)"
        SdkToolsPath = "$(TargetFrameworkSDKToolsDirectory)"
        EnvironmentVariables = "$(SGenEnvironment)"
        SerializationAssembly = "$(IntermediateOutputPath)$(_SGenDllName)"
        Platform = "$(SGenPlatformTarget)"
        Types = "$(SGenSerializationTypes)">
            <Output TaskParameter = "SerializationAssembly" ItemName = "SerializationAssembly"/>
    </SGen>
</Target>

Фактически, перемещение добавления из пункта 4 в пункт 3 приведет к выполнению <GenerateSerializationAssemblies> на </ GenerateSerializationAs‌ semblies> для всех условий PropertyGroup.

Michel van Engelen 04.05.2017 15:51

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

<!-- Check the platform target value and if present use that for a correct *.XmlSerializer.dll platform setup (default is MSIL)-->
<PropertyGroup Condition = " '$(PlatformTarget)'=='' ">
  <SGenPlatform>$(Platform)</SGenPlatform>
</PropertyGroup>
<PropertyGroup Condition = " '$(PlatformTarget)'!='' ">
  <SGenPlatform>$(PlatformTarget)</SGenPlatform>
</PropertyGroup>

<!-- Delete the file because I can't figure out how to force the SGen task. -->
<Delete Files = "$(TargetDir)$(TargetName).XmlSerializers.dll" ContinueOnError = "true" />
<SGen
  BuildAssemblyName = "$(TargetFileName)"
  BuildAssemblyPath = "$(OutputPath)"
  References = "@(ReferencePath)"
  ShouldGenerateSerializer = "true"
  UseProxyTypes = "false"
  KeyContainer = "$(KeyContainerName)"
  KeyFile = "$(KeyOriginatorFile)"
  DelaySign = "$(DelaySign)"
  ToolPath = "$(SGenToolPath)"
  SdkToolsPath = "$(TargetFrameworkSDKToolsDirectory)"
  EnvironmentVariables = "$(SGenEnvironment)"
  Platform = "$(SGenPlatform)">
  <Output TaskParameter = "SerializationAssembly" ItemName = "SerializationAssembly" />
</SGen>

Я немного опоздал на вечеринку, но мне было сложно работать с предыдущим ответом. В частности, Visual Studio вылетала всякий раз, когда я пытался просмотреть свойства своего проекта. Я полагаю, это было связано с тем, что он больше не понимал, как читать файл csproj. Тем не менее ...

Добавьте в командную строку события после сборки следующее:

"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\sgen.exe" "$(TargetPath)" /force

Это будет использовать sgen.exe напрямую для перестройки сборки сериализации XML каждый раз, когда вы создаете свой проект для отладки или выпуска.

Другие вопросы по теме