The wacky world of serializers

 Recently I’d set my debug exception handling to catch pretty much every exception thrown and I kept seeing a rather strange error…
System.IO.FileNotFoundException occurred
  Message="Could not load file or assembly myType.XmlSerializers"
 
What was odd about this error is that although the type in question was being serialized it wasn’t overloading any serialization code, so why the exception? The question did the rounds of the development team and a colleague discovered the truth. It turns out that as an optimization .net searches for a special optimized serialization version of the type, based on the type’s names. If it finds it, it uses it. If not a file not found exception is raised and then automatically handled and the default serializer is called into play. What I find odd about this concept is that in order to use an optimization, that I would have to write anyway, the framework makes an expensive disk access followed by an exception. So the effect is that if I don’t implement the optimization I get an extra performance hit!
 
Advertisements

Simple way to Serialize an object to a string

I’m the first to admit that the number of streams and serializing methods can be confusing. I wanted a quick and simple way to test my serialize code by persisting an object into a string. A quick google later and I had found a number of overly complicated examples, so here is my very simple method…
                        XmlSerializer serializer = new XmlSerializer(typeof(MyType));
            string resultingXml = null;
            using (StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture))
            {
                serializer.Serialize(stringWriter, myObject);
                resultingXml = stringWriter.ToString();
            }

Setup.EXE bootstrap for WiX and/or msi

Creating msi files using WiX is normally great, however one thing that is terrible is when you want your users to upgrade a product. Rather than simply selecting the msi they are required to issue

MSIEXEC /i My.msi REINSTALL=ALL REINSTALLMODE=vomus

Not exactly user friendly. So it was time to create a nice setup.exe bootstrap to detect when an upgrade was needed and issue the horror statement. A quick tour around the Windows SDK brought up the their sample. Written in Win32/C++ it seemed to be over complicated especially since I know the product is only ever going onto machines with .net pre-installed. So I wrote the following little csharp console code that does the trick for my requirements.

 

static

void Main(string[] args)

{

Type componentType = Type.GetTypeFromProgID("WindowsInstaller.Installer");

if (componentType == null)

{

Console.WriteLine("Windows Installer is either not installed or could not be located");

return;

}

object componentInstance;

try

{

componentInstance =

Activator.CreateInstance(componentType);

}

catch (Exception e)

{

Console.WriteLine("Windows Installer is either not installed or could not be located: " + e.Message );

return;

}

 

object returnType = componentType.InvokeMember("Products", BindingFlags.GetProperty, null, componentInstance, null);

IEnumerable stringList = (IEnumerable)returnType;

bool foundProduct = false;

foreach (string product in stringList)

{

if (product == "{YOURPRODUCT_GUID}")

{

foundProduct =

true;

break;

}

}

if (foundProduct)

{

System.Diagnostics.

Process.Start(@"msiexec",

@"/i My.msi REINSTALL=ALL REINSTALLMODE=vomus");

}

else

{

System.Diagnostics.

Process.Start(@"msiexec", "My.msi");

}

}

 

Fun with Enums

One of the seemingly lesser known features of Enums is their ability to convert to and from the name rather than the value, so I thought I’d do a quick refresher.

Consider the following Enum…
Medal.Bronze = 0
Medal.Silver = 1
Medal.Gold = 2

The majority of cases people leave it as an int (can be any non-char integral type). However, what happens when you want to store/persist the type? If I was to save this to a disk file I might choose to use XML and have a result like…
<Medal>2</Medal>
Then when I load the XML back I can easily convert it back…
Medal medal = (int)Convert.ToInt32("2");
However, I don’t actually like this, the value of 2 has no real meaning to the reader, I’d much prefer to see
<Medal>Gold</Medal>
Well it is possible. To save the name rather than the value you can use ToString and a format string…
medal.ToString("G");
Reading the name back into the enum uses the often overlooked Parse method…
Medal medal = (Medal)Enum.Parse(typeof(Medal), "Gold");
Admittedly this doesn’t solve localization problems of having XML, "human readable" but I prefer it.

NotSupportedException

I had written some code that implemented a particular interface where I only wanted to support a small set of the functions. So when I used Visual Studio’s snippet I left the throw new Exception("Not yet implemented") alone. My ever knowing colleague explained to me that this was a known problem with the snippet and it should really use…
throw new NotSupportedException

I thought this was a great find since I hated raising such a woolly exception.

Support implicit/explicit conversion in C# for VB.NET

Today I hit an annoying problem with VB.NET using components written in C#. The basic problem is that I have an object called Field with a Value property of type object written in C#. The client code is written in VB.NET and wants to access the Field’s value without specifying the Value property, e.g.

Dim myField as Field = new Field()
myField.Value = 13

If CInt(myField) = 13 or myField = 13…

The initial problem is that a Field is not an int, so you’ll get an invalid cast, fair enough. So I implemented the implicit/explicit conversion operators available in C#.

Field myField = new Field();
myField.Value = 13

if ((int)myField==13)…

The above, written in C#, now works but the previous VB.NET still fails! The problem is that VB.NET simply doesn’t call op_Implicit/op_Explicit functions exposed by the C# code. Delving into the Visual Basic engine you can see that under the covers it use IConvertable to do all of its conversions. So if you want VB.NET to understand that House = 7 really means House.Number = 7 then you need to implement IConvertable in the C# component.

After implementing IConvertable the above code sprang into life.

Mono == Frustration

Finally managed to find a 1/2 decent code editor for the Mac (smultron) so I thought I port my Wake Up On Lan code to mono and run it on the Mac. What an annoying tool mono is. After using the tools of dinosaurs (Terminal) I asked the compiler to do its work. It came back with… (4, 255+) Expecting ‘;’. Well fine but what the **!* does that mean? I sort of assumed that it was column and row. So I went to the 5th line and stuck in some rubbish characters to confirm my theory… (1, 124) Expecting ‘;’. Eh? Now I understand why they don’t supply some lovely rich IDE but I would hope that the compiler gives useful error messages not some random value that makes it impossible to use. Ok I’ll look up the error codes, couldn’t find any documentation on that. Off to the forums, surely I must just have something configured incorrectly. What forum, must be a community support. Nope some link to a commercial company. Ah here we go…an email list. What is this? A tool for the uber geek who takes pleasure in finding the most painful and awful way to communicate? I’ve half a mind to simply give up on this if "they" simply want to keep it a dark room project.

[Edit] A plus in Mono’s column… Although the error message is still *rubbish* I finally discovered that I had some generics code and I was using the v1 compiler. So I downloaded the latest version of Mono and updated (nice that it updated the existing version) and used the gmcs compiler (v2) and the file compiled without problems, so expect a WOL for OSX in the near future.