Создание сборки Xml Serialization как части моей сборки

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

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

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


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

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


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

Как получить визуальную студию для автоматической сборки сборки XML Serialization?


Обновление: сборка "Сериализация сборки": при установке ничего не отображается.

Ответ 1

Вот как мне удалось это сделать, изменив MSBUILD script в моем файле .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>

Это работает для меня.

Ответ 2

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

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

SGenUseProxyTypes

Логическое значение, указывающее, являются ли типы прокси должен быть сгенерирован SGen.exe. Цель SGen использует это свойство для установите флаг UseProxyTypes. Это свойство по умолчанию имеет значение true, и там не является пользовательским интерфейсом, чтобы изменить это. Чтобы создать сериализованную сборку для не-webservice, добавьте это свойство в файл проекта и установите его до false перед импортом Microsoft.Common.Targets или С#/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>

Ответ 3

Другие ответы на этот вопрос уже упоминались в настройке Project Properties- > Build → Generate Assemblies Assemblies, но по умолчанию это приведет к генерации сборки только в том случае, если существует " веб-служба XML прокси-типов".

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

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

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

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

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

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

Ответ 4

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

Шаги для предварительной генерации сборок сборки

(с частями от http://msdn.microsoft.com/en-us/library/ff798449.aspx)

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

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

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

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

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

    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>

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

  • В обозревателе решений щелкните правой кнопкой мыши только что отредактированный проект и нажмите "Обновить проект".

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


Описание

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

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

0x80131040: Расположенное определение манифеста сборки не соответствует ссылке на сборку

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

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

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

Просмотрите определение задачи SGen для TargetFrameworkVersion 4.0 из

Путь установки Windows\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>

Ответ 5

В случае, если кто-то другой столкнется с этой проблемой внезапно после того, как все работает нормально раньше: для меня это связано с отключением флажка "Включить только мой код (только управляемый)" в меню опций (Options → Debugging) (который автоматически отключается после установки .NET Reflector).

EDIT: Разумеется, это исключение происходило раньше, но когда "включить только мой код" выключен, помощник отладки (если он включен) остановится в этот момент при броске.

Ответ 6

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

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

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

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

Ответ 7

Посмотрите свойства в решении. На вкладке "Сборка" внизу находится раскрывающийся список "Создание сборки Serialization"

Ответ 8

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

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