There is an overhead incurred when using serialization in your application, which is caused by generation of a ‘helper’ assembly for each type that is serialized with XmlSerializer (per-process-per-domain). (Btw – this has subtle adverse effect – if you use serialization – your application should have Read/Write permissions to %windir%\temp folder).
This overhead may be avoided by using Sgen.exe tool to pre-generate serialization assemblies.
Basically it should be pretty straightforward, especially if your FooBar.dll assembly for which you pre-generating serialization assembly doesn’t has a lot of references. Unfortunately – if you do have a lot of references – you would have to add them all using /reference:c:\foo1\foo1.dll /reference:c:\foo2\foo2.dll /reference:c:\foo3\foo3.dll ……
Here is a workaround:
To generate serialization assembly manually (could be done as a post-build step):
1) Visual Studio –> Foo.csproj –> Properties –> Build –> Generate Serialization Assembly –> On
You would expect it to work automatically now – but it wouldn’t, or saying it more precisely it would create serialization assembly only if your assembly includes proxy types (e.g. web-services).
Anyway – build your assembly, open MSVC output window and look for sgen.exe line in the end of output.
2) Copy whole sgen.exe line – it would include all the references needed.
3) Remove from it /proxytypes parameter – this will cause sgen.exe to generate serializers for regular types.
4) Add /force parameter to force overwrite of previously created assembly.
Now you almost done except of following caveats:
1) If you have types with the same name in different namespaces you would get error saying something like:
Error: There was an error reflecting type ‘FooNamespace.Foo’ – Types ‘FooNamespace1.Foo’ and ‘FooNamespace2.Foo’ both use the XML type name. Use XML attributes to specify a unique XML name and/or namespace for the type.
To resolve it – differentiate your types by specifying XML namespace:
1: using System.Xml.Serialization;
2:
3: [XmlType(Namespace = "urn:Foo1")]
4: [XmlRoot(Namespace = "urn:Foo1")]
5: public class Foo{}
2) If you have properties with readonly or internal properties, or internal types – you would get the following error:
Error … property or indexer cannot be assigned to it is read only.
You may either mark such property with [XmlIgnore] attribute or (for internal) – add following line to AssemblyInfo.cs file:
[assembly: InternalsVisibleTo("<AssemblyName>.XmlSerializers, PublicKeyToken=null")]
You may still add it as part of build process manually modifying MSBUILD script in .csproj file.
Look here or here for details.
Technorati Tags:
C#,
.NET,
Sgen.exe