Этот код создает исключение 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?
Обновление: параметр «Создать сборку сериализации: при включении», похоже, ничего не делает.





Посмотрите свойства решения. На вкладке сборки внизу есть раскрывающийся список под названием «Создать сборку сериализации».
Похоже, это ничего не дает.
вы должны переключить его на «Вкл.». Авто, похоже, ничего не делает
ничего не производит, даже если установлено на ON
который работает только для типов прокси веб-служб - в противном случае следует использовать задачу MSBuild <SGen /> (или командный инструмент sgen.exe).
Открыта проблема с MS Connect, которая означает, что она была закрыта по причине "По замыслу" connect.microsoft.com/VisualStudio/feedback/details/123088/…
Вот как мне удалось это сделать, изменив сценарий 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 просто работал с ними.
Не забудьте включить платформу для SGen, если делаете сборки для конкретной платформы, например: Platform = "$ (Platform)". Я получал ошибку вроде: WRN: сравнение имени сборки привело к несоответствию архитектуры процессора: Ref x86, Def MSIL.
Это прекрасно генерирует файлы DLL, но, похоже, все еще производит генерацию сборки на лету. Нужно ли мне что-то делать с этой DLL после ее создания?
Просто разверните его. Вы можете использовать отладчик, чтобы точно узнать, какой тип вызывает создание динамической сборки. Даже если вы сериализуете все свои типы, они наверняка состоят из других типов, некоторых типов фреймворка, которые могут потребовать создания сборки.
Это происходит в .DLL, где определены классы, или в проекте для .exe? Я полагаю, поскольку это MSBuildAllProjects, он правильно помещается в .exe?
В других ответах на этот вопрос уже упоминался параметр 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), исправление одной строки!
Я протестировал и подтвердил, что это работает в Visual Studio 2008. Большое спасибо за то, что откопали это.
Согласовано! Отличный ответ
Мне не хватало этой части, наконец-то удалось решить эту проблему. Очень полезный ответ!
Я попробовал это, и он сгенерировал 32-битный XmlSerializers.dll, хотя мой проект настроен для x64. Есть ли параметр "разрядности" для XmlSerializers?
создание нового определения задачи sgen ломает муху на лету. просто установите необходимые переменные, чтобы задача работала должным образом. В любом случае в документации Microsoft отсутствует важная информация.
(с деталями из http://msdn.microsoft.com/en-us/library/ff798449.aspx)
В файле .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: 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.
Несколько отличное от решения резервное копирование мозга решение может заключаться в том, чтобы напрямую указать целевую платформу именно там, где вы должны ее использовать, например:
<!-- 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 каждый раз, когда вы создаете свой проект для отладки или выпуска.
Я также решил использовать Sgen, который работает для обычных типов. Однако это не позволяет мне создавать экземпляры XmlSerializer для массивов этих типов. Если вы столкнулись с этим, напишите здесь: stackoverflow.com/questions/1844870/…