I’ve discovered today that CodeDom classes are serializable. So what does that have to do with anything, right?

When you drop a control into a WinForm and hit the save button, the designer turns the state of your controls into code and puts that code in the form’s InitializeComponent method.

To get the code for InitializeComponent, Visual Studio looks at the class being designed (the root component) and asks for its RootDesignerSerializer. This serializer is a class derived from CodeDomSerializer. It has a Serialize method and a Deserialize method. Serialize takes the state of your class and all of its children and converts them into a CodeDom tree. Then the CodeDom tree gets turned into source code and saved with your form. Deserialize takes a CodeDom tree and returns the original object. Deserialize is similar to using reflection. Each statement tells Visual Studio what property to set on each control to make it look as you intended in the designer.

So here’s what I did…I wrote my own RootDesignerSerializer. (It’s not as complicated as it sounds). It’s a class derived from CodeDomSerializer. In its constructor, I create the standard RootDesigner class.

Type rootSerializerType = Type.GetType(”System.ComponentModel.Design.Serialization.RootCodeDomSerializer, System.Design, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”,true);
_rootSerializer = Activator.CreateInstance(
rootSerializerType,
BindingFlags.CreateInstance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
null,
null,
null) as CodeDomSerializer;

Then in the Serialize method, I tell the standard .NET class to Serialize. I get CodeDom back from the Serialize method. Then, because CodeDom is serializable, I save the CodeDom statements to a file.

if (_rootSerializer != null)
serResult = _rootSerializer.Serialize(manager,value);

//serialize all of the code to an external file
FileStream fs = new FileStream(”C:\\sercontrol.txt”,FileMode.Create);
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(fs,serResult);
fs.Close();

On the Deserialize, I read the file and give the CodeDom tree to the standard Deserialize function which returns the original object.

if (File.Exists(”C:\\sercontrol.txt”))
{
//deserialize the result from a file
FileStream fs = new FileStream(”C:\\sercontrol.txt”,FileMode.Open);
SoapFormatter formatter = new SoapFormatter();
codeObject = formatter.Deserialize(fs);
fs.Close();
}

if (_rootSerializer != null)
desResult = _rootSerializer.Deserialize(manager,codeObject);

To get VS to use my serializer, I put this attribute on my control:

[RootDesignerSerializerAttribute(typeof(MyRootSerializer),typeof(CodeDomSerializer),true)]

What this means so far is that at design time I can make Visual Studio save the code that would normally go into InitializeComponent to an external file. What I need to do next is make it read this tree at run time and apply it to my form. This will give me the ability to in essense have a code behind file.

More later…