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.

Programmatically Wake Up On Lan using .net

I’ve been meaning to write a web site to list a number of machines and allow the user to issue a Wake Up On Lan command to them. Looking around the web I found a great VB sample to issue the command. However, I didn’t want to pollute my nice c# with yukky VB  so converted it to c# and changed a few bits to bring it align with Microsoft standards.
 

using

System;

using

System.Collections.Generic;

using

System.Text;

using System.Net;

using

System.Net.Sockets;

using

System.Globalization;

 

namespace

Utilities.Network

{

/// <summary>

/// Utility class to wake machines up that are configured to "Wake Up On Lan"

/// </summary>

/// <remarks>Code orginally written in VB from http://www.lucamauri.com/snippet/snip.aspx?id=6</remarks>

public sealed class WakeUpOnLan

{

/// <summary>

/// Initialise using the default values

/// </summary>

/// <remarks>The default IPEndPoint transmit on port 7. Other choices for WOL are port 0 or 9</remarks>

public WakeUpOnLan()

{

this.endPoint = new IPEndPoint(IPAddress.Broadcast, 7);

}

/// <summary>

/// Initialise using a specific port

/// </summary>

/// <param name="port">A valid port number</param>

/// <remarks>If the port number is invalid, the IPEndPoint is created to port 7. Ports normally used for WOL are 0, 7 or 9.</remarks>

public WakeUpOnLan(int port)

{

if (port >= 0 && port < 65535)

{

endPoint =

new IPEndPoint(IPAddress.Broadcast, port);

}

else

{

endPoint =

new IPEndPoint(IPAddress.Broadcast, 7);

}

}

 

/// <summary>

/// The IPEndPoint object that will act as a trasport for the packet.

/// It is automatically created by New statement, but you can modify it or read it.

/// </summary>

/// <value>An IPEndPoint object</value>

/// <returns>An IPEndPoint object</returns>

/// <remarks>Normally there is no need to change this manually.</remarks>

public IPEndPoint EndPoint

{

get

{

return this.endPoint;

}

set

{

this.endPoint = value;

}

}

/// <summary>

/// The target machine Network Interface Card MAC address.

/// It must be dash-separated, i.e. in the 11-22-33-44-55-66 form

/// </summary>

/// <value>A string with dash-separated values</value>

/// <returns>A string with dash-separated values</returns>

/// <remarks>The standard (IEEE 802) separator for cotet are dash (-) and semicolon (:). I resolved to use dashes only in order to avoid any possible confusion and misunderstanding with upcoming IPv6 addressing space.</remarks>

public string MacAddress

{

get

{

StringBuilder textMAC = new StringBuilder();

foreach (byte currByte in this.macAddress)

{

textMAC.Append(

"-");

textMAC.Append(currByte.ToString(

"X2"));

}

return textMAC.ToString().Substring(1);

}

set

{

if (String.IsNullOrEmpty(value))

{

throw new FormatException(MacFormatMessage);

}

Queue<byte> values = new Queue<byte>();

string[] hexValues = value.Split(‘-‘);

if (hexValues.Length != 6)

{

throw new FormatException(MacFormatMessage);

}

foreach (string currByte in hexValues)

{

byte convertedByte;

if (Byte.TryParse(currByte, System.Globalization.NumberStyles.HexNumber,

CultureInfo.InvariantCulture, out convertedByte))

{

values.Enqueue(convertedByte);

}

else

{

throw new FormatException(MacFormatMessage);

}

}

this.macAddress = values.ToArray();

}

}

/// <summary>

/// Total bytes sent by WakeIt method. It is 0 until the method is called at least once for this class instance.

/// </summary>

/// <returns>Integer value, total bytes trasmitted</returns>

/// <remarks></remarks>

public int BytesSent

{

get

{

return this.bytesSent;

}

}

/// <summary>

/// It represent the Magic Packet broadcasted.

/// </summary>

/// <returns>String containing the text parsing of the Magic Packet</returns>

/// <remarks></remarks>

public string PacketSent

{

get

{

return packetSent;

}

}

/// <summary>

/// Creates a WOL Magic Packet, the datagram that will awake the target PC upon broadcast on the network.

/// </summary>

/// <param name="macAddress">An array of byte representing the target machine Network Interface Card MAC address</param>

/// <returns>An array of byte representing the Magic Packet</returns>

/// <remarks>This method can be used indipendently from the rest of the class. If necessary it can create a Magic Packet just providing the MAC address.</remarks>

private byte[] MagicPacket(byte[] macAddress)

{

if (macAddress.Length == 0)

{

throw new FormatException("Invalid MAC address");

}

byte[] payloadData = new byte[0];

StringBuilder packet = new StringBuilder();

 

payloadData =

new byte[HeaderLength + MacLength * repMAC];

for (int i = 0; i < HeaderLength; i++)

{

payloadData[i] =

Byte.Parse("FF", System.Globalization.NumberStyles.HexNumber);

}

for (int i = 0; i < repMAC; i++)

{

for (int j = 0; j < MacLength; j++)

{

payloadData[HeaderLength + i * MacLength + j] = macAddress[j];

}

}

foreach (byte currLoad in payloadData)

{

packet.Append(

"-");

packet.Append(currLoad.ToString("X2"));

}

packetSent = packet.ToString().Substring(1);

 

return payloadData;

}

private int SendUdp(byte[] payload, IPEndPoint endPoint)

{

int byteSend;

if ((payload != null) && (endPoint != null))

{

Socket socketClient = new Socket(endPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);

socketClient.Connect(endPoint);

byteSend = socketClient.Send(payload, 0, payload.Length,

SocketFlags.None);

socketClient.Close();

}

else

{

byteSend = 0;

}

return byteSend;

}

/// <summary>

/// It is the main method of the class. It must be called after the MAC address has been set. It does not return any code, you can see the result of the operation with the bytesSent and packetSent properties of this class.

/// </summary>

/// <remarks></remarks>

public void WakeIt()

{

bytesSent = SendUdp(MagicPacket(macAddress), endPoint);

}

const int HeaderLength = 6;

const int MacLength = 6;

const int repMAC = 16;

const string MacFormatMessage = "Mac Format should be; XX-XX-XX-XX-XX, e.g. 00-13-71-BC-C2-CE";

IPEndPoint endPoint;

byte[] macAddress;

int bytesSent = 0;

string packetSent;

}

}

Calling the instance of a ContextBoundObject

ContextBoundObjects are useful for implementing Aspect Orientated Programming (AOP), however one thing that I wanted to do was to call methods on the instance that the context "shadows". Since it caused me some pain I though I’d publish it here to avoid others suffering as I did.
 
1. Save the MarshalByRefObject that is passed into the AttributeContext, this represents the object that we’re shadowing

public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)

2. Assuming you can put your AOP attribute on any class, you’ll need to get hold of the type that is really inside the Marshalled object. There are a number of ways of doing this, this was the first mechanism I tried and it worked so I left it at this

private

void Postprocess(IMessage msg, IMessage msgReturn)

…msg.Properties[

"__TypeName"];

3. Marshal the object into the discovered type and call methods on it. All done.
 

Type

sourceType = Type.GetType(typeName);

ObjRef objectRef = RemotingServices.Marshal(this.sourceMarshalByRefObject,null,sourceType);

object o = Activator.GetObject(sourceType, objectRef.URI);

if (o is IMyKnownInterface)

{

IMyKnownInterface myInterface = (IMyKnownInterface)o;

myInterface.MyMethod()

 

Windows Presentation Framework, first look

I had my first real play with the Windows Presentation Framework (WPF). The first thing that struck me is how like the web model it is. For example, through the use of various services it provides the cascading down of properties and the bubbling up of events. So you can mark a grand-parent property, e.g. color, and if any child node doesn’t specify a colour they’ll automatically have their parents colour value. Similarly the event model is like the web.  You  fire an  event in a child element and the event can bubble up through all of its ancestors, any of which can handle the event.

I only managed a very quick play with the beta Visual Studio Add-in, created a quick "hello world" style application from a button click. I’m not sure if it’s a clumsy beta or it going to work this way but I didn’t get my nice event handler template by double clicking the button. Oh no, I had to guess at event handling code (almost identical to the usual one) and guess where in the Xaml I had to add the click attribute to wire-up the event. But it worked and I hope to have a longer play soon.

How to ignore a field/property during serialization

I’ve hit the problem of serializing a property for the last time. When you create a type that contains a non-serializable type, in my case a CultureInfo class, you cannot automatically serialize the type – you get issues about "does not contain a public constructor", "problem reflecting the type", etc. Unfortunately this isn’t caught at compile time and you have to wait until an attempt is made to serialize the containing object. What to do about it? The more complicated choice is to write some custom serialization code, but really, most of the time I just want to serialize pretty simple objects. So my preference is to mark the class as serializable and let the client choose how to serialize it, i.e. via Binary or Xml "serializers". The framework provides a couple of attributes for this, and this is where the gotcha lives.

The first attribute, [NonSerialized], should be applied to field members and informs the standard serialization methods to ignore the field. The second attribute, [System.Xml.Serialization.XmlIgnore], should be applied to public properties and informs the Xml Serializer to ignore the property. The combination of the two should be enough to stop the field from being serialized regardless of the serializer the client chooses to use.
Quick pseudo example:

[NonSerialized],
private SomeUnFriendlyType myType:

[System.Xml.Serialization.XmlIgnore]
public SomeUnFriendlyType MyType()
….