This code produces a FileNotFoundException, but ultimately runs without issue:
void ReadXml() { XmlSerializer serializer = new XmlSerializer(typeof(MyClass)); //... }
Here is the exception:
A first chance exception of type 'System.IO.FileNotFoundException' occurred in mscorlib.dll
Additional information: Could not load file or assembly 'MyAssembly.XmlSerializers, Version=1.4.3190.15950, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
It appears that the framework automatically generates the serialization assembly if it isn't found. I can generate it manually using sgen.exe, which alleviates the exception.
How do I get visual studio to generate the XML Serialization assembly automatically?
Update: The Generate Serialization Assembly: On setting doesn't appear to do anything.
The serialization assembly improves the startup performance of a XmlSerializer when it serializes or deserializes objects of the specified types.
As with the CreatePo method, you must first construct an XmlSerializer, passing the type of the class to be deserialized to the constructor. Also, a FileStream is required to read the XML document. To deserialize the objects, call the Deserialize method with the FileStream as an argument.
XML serialization can also be used to serialize objects into XML streams that conform to the SOAP specification. SOAP is a protocol based on XML, designed specifically to transport procedure calls using XML. To serialize or deserialize objects, use the XmlSerializer class.
This will leverage sgen.exe directly to rebuild the Xml Serialization assembly every time you build your project for Debug or Release. Look in the properties on the solution. On the build tab at the bottom there is a dropdown called "Generate Serialization assembly" This does not appear to be producing anything. you have to toggle it to "On".
Ensure * Solution Explorer is opened. Right-click on the ClassLibrary1 (Project Name), select Properties Go directly into the Build tab, at the bottom of the screen, for Generate serialization assembly, change the selection to On (default is Auto ). Save the properties and Build the project. You will see the above error in the output window:
Introducing XML Serialization. To serialize all an object's fields and properties, both public and private, use the DataContractSerializer instead of XML serialization. The central class in XML serialization is the XmlSerializer class, and the most important methods in this class are the Serialize and Deserialize methods.
The XmlSerializer creates C# files and compiles them into .dll files to perform this serialization. In .NET Framework 2.0, the XML Serializer Generator Tool (Sgen.exe) is designed to generate these serialization assemblies in advance to be deployed with your application and improve startup performance.
As Martin has explained in his answer, turning on generation of the serialization assembly through the project properties is not enough because the SGen task is adding the /proxytypes
switch to the sgen.exe command line.
Microsoft has a documented MSBuild property which allows you to disable the /proxytypes
switch and causes the SGen Task to generate the serialization assemblies even if there are no proxy types in the assembly.
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
As the documentation suggests you must modify your project file by hand, but you can add the SGenUseProxyTypes
property to your configuration to enable generation. Your project files configuration would end up looking something like this:
<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>
This is how I managed to do it by modifying the MSBUILD script in my .CSPROJ file:
First, open your .CSPROJ file as a file rather than as a project. Scroll to the bottom of the file until you find this commented out code, just before the close of the Project tag:
<!-- 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> -->
Now we just insert our own AfterBuild target to delete any existing XmlSerializer and SGen our own, like so:
<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>
That works for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With