public string Serialize(string designerDocumentFragment)
{
if (host == null)
throw new Exception("The document cannot be persisted without a host");
string serializedDoc = string.Empty;
StringWriter writer = new StringWriter ();
//keep method argument meaningfully named, but keep code readable!
string frag = designerDocumentFragment;
int length = frag.Length;
int pos = 0;
SMode mode = SMode.Free;
while (pos < length)
{
char c = frag [pos];
switch (mode)
{
//it's freely copying to output, but watching for a directive or control placeholder
case SMode.Free:
if (c == '<')
{
if ((pos + 10 < length) && frag.Substring (pos + 1, 10) == "aspcontrol") {
mode = SMode.ControlId;
pos += 10;
break;
}
else if ((pos + 20 < length) && frag.Substring (pos + 1, 20) == "directiveplaceholder") {
mode = SMode.DirectiveId;
pos += 20;
break;
}
}
writer.Write (c);
break;
//it's found a directive placeholder and is scanning for the ID
case SMode.DirectiveId:
if (c == 'i' && (pos + 4 < length) && frag.Substring (pos, 4) == "id=\"") {
int idEnd = frag.IndexOf ('"', pos + 4 + 1);
if (idEnd == -1) throw new Exception ("Identifier was unterminated");
int id = Int32.Parse (frag.Substring (pos + 4, (idEnd - pos - 4)));
//TODO: more intelligent removal/copying of directives in case of fragments
//works fine with whole document.
string directive = RemoveDirective (id);
writer.Write (directive);
mode = SMode.DirectiveEnd;
pos = idEnd;
}
break;
//it's found a control placeholder and is scanning for the ID
case SMode.ControlId:
if (c == 'i' && (pos + 4 < length) && frag.Substring (pos, 4) == "id=\"") {
int idEnd = frag.IndexOf("\"", pos + 4);
if (idEnd == -1) throw new Exception ("Identifier was unterminated");
string id = frag.Substring (pos + 4, (idEnd - pos - 4));
DesignContainer dc = (DesignContainer) host.Container;
Control control = dc.GetComponent (id) as Control;
if (control == null) throw new Exception ("Could not retrieve control "+id);
ControlPersister.PersistControl (writer, control);
mode = SMode.ControlEnd;
pos = idEnd;
}
break;
//it's found the control's ID and is looking for the end
case SMode.ControlEnd:
if (c == '<' && (pos + 13 < length) && frag.Substring (pos, 13) == "</aspcontrol>") {
pos += 12;
mode = SMode.Free;
}
break;
//it's found the placeholder's ID and is looking for the end
case SMode.DirectiveEnd:
if (c == '/' && (pos + 2 < length) && frag.Substring (pos, 2) == "/>") {
pos += 1;
mode = SMode.Free;
}
break;
}
pos++;
}
serializedDoc = writer.ToString ();
writer.Close ();
return serializedDoc;
}