More than one way to skin a cat....
Still on the subject of the BasicDesignerLoader class......
I have written a forms designer, implementing IDesigner etc., and this works
very well. I am having trouble implementing the BasicDesignerLoader though..
The PerformFlush sub will successfully write the controls to a file using a
CodeDOMSerializer and the VBCodeProvider class. The file does indeed contain
all the information I want it to - horray!
The problem is getting it back again. I cannot see any methods to read the
file and convert the VB back into the CodeStatementCollection on the CodeDOM
object. I am sure the methods would also be same for CS as well.
So then, how do I convert the VB code from a text file back into the
IDesignerHost, in other words load the layout from a VB file?
Thanks,
David
Hi David,
Thanks for your post.
In your another post "XML Serialization in the BasicDesignerLoader Class",
I have provided you a Microsoft sample DesignerHost. In this sample, it
provided 3 ways to serialize the entire form designer: C# code file, VB.net
code file and Xml code file. However, it only provide the implementation to
deserialize Xml code file.
But, deserializing C#/VB.net code file is always the same way as the
serialization code. Please see the code snippet below:
// Autogenerates member declaration and InitializeComponent()
// in a new CodeTypeDeclaration
//
RootDesignerSerializerAttribute a =
TypeDescriptor.GetAttributes(root)[typeof(RootDesignerSerializerAttribute)]
as RootDesignerSerializerAttribute;
Type t = host.GetType(a.SerializerTypeName);
CodeDomSerializer cds = Activator.CreateInstance(t) as CodeDomSerializer;
IDesignerSerializationManager manager =
host.GetService(typeof(IDesignerSerializationManager)) as
IDesignerSerializationManager;
CodeTypeDeclaration td = cds.Serialize(manager, root) as
CodeTypeDeclaration;
It actually use reflection to get the CodeDomSerializer associated with the
component/control, then invoke CodeDomSerializer.Serialize to serilize the
control. We should do the reverse work, just get the CodeDomSerializer and
invoke its Deserialize() method to get object instance back.
Hope this helps
Best regards,
Jeffrey Tan
Microsoft Online Partner Support

Signature
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
David Whitchurch-Bennett - 23 Sep 2005 11:31 GMT
Hi Jerrrey,
Thanks for the reply. I already have the serialize working great, and here
is the code that I am using (in VB I am afraid!)
Protected Overrides Sub PerformFlush(ByVal serializationManager As
System.ComponentModel.Design.Serialization.IDesignerSerializationManager)
' create Code Document Object Model Serializer to get code statements
Dim codeDOM As CodeDomSerializer =
serializationManager.GetSerializer(GetType(IDesignerHost),
GetType(CodeDomSerializer))
' get code statement collection from the serializer
Dim codeStatementCollection As CodeStatementCollection =
codeDOM.Serialize(serializationManager, _host.RootComponent)
csc = codeStatementCollection
' create vb provider to translate statements into VB text
Dim vbProvider As Microsoft.VisualBasic.VBCodeProvider = New
Microsoft.VisualBasic.VBCodeProvider
' test writer
Dim writer As New System.IO.StreamWriter("C:\Test.txt")
writer.AutoFlush = True
' loop through each statement, and write to the text writer
For Each s As CodeDom.CodeStatement In codeStatementCollection
vbProvider.GenerateCodeFromStatement(s, writer, New
System.CodeDom.Compiler.CodeGeneratorOptions)
Next
writer.Close()
End Sub
When trying to deserialize, I have the following code so far.
Protected Overrides Sub PerformLoad(ByVal serializationManager As
System.ComponentModel.Design.Serialization.IDesignerSerializationManager)
' read the VB text file
Dim reader As New System.IO.StreamReader("C:\Test.txt")
' somehow get VB code back into CodeStaementCollection
Dim codeStatementCollection As CodeStatementCollection
' create Code Document Object Model DeSerializer
Dim codeDOM As CodeDomSerializer =
serializationManager.GetSerializer(GetType(IDesignerHost),
GetType(CodeDomSerializer))
' deserialize into the root component object
Dim formObject As Form = codeDOM.Deserialize(serializationManager,
codeStatementCollection)
' somehow get the form object into the DesignerHost
I have two problems here.
Firstly, _host.RootComponent is read-only (_host is the DesignerHost), so
how to I get my deserialized form back into this. (I will read the other
sample you suggested as well)
Secondly and more importantly, I can't translate the VB text file back into
CodeDom statements. I have searched for how to do this, but cannot find any
information. There must be a way as the VB.NET designers do it all the time.
I hope this all makes sense, and I have probably missed something very
obvious! Hopefully you can help me out here!
David.
David Whitchurch-Bennett - 23 Sep 2005 15:29 GMT
Hi Jeffrey,
Well, I have been working on this all day so far, and I've got a little
further. As mentioned in the above post, I can deserialize no problem. I have
also added code to serialize the CodeDOM statement collection to a binary
file, rather than to VB code. This is great, and it works OK.
I can also deserialize the binary file back to CodeDOM statemements, and I
have tested this by writing them back to VB code, and it looks fine, so I can
read and write the CodeDOM statement collection - this is great.
The final thing is can't seem to get working is these two lines...
' create Code Document Object Model DeSerializer
Dim codeDOM As CodeDomSerializer =
serializationManager.GetSerializer(GetType(IDesignerHost),
GetType(CodeDomSerializer))
' deserialize into the root component object
codeDOM.Deserialize(serializationManager, codeStatementCollection)
I am sure something is missing (the deserialize function should return an
object, and I need to add it to the designer I guess), BUT it won't create
that object, which should be a form. Instead, it throws the following
exception, which I can't understand as the Form type is definately referenced
in the project.
System.ComponentModel.Design.Serialization.CodeDomSerializerException was
unhandled by user code
HelpLink="SerializerTypeNotFound"
Message="Could not find type 'System.Windows.Forms.Form'. Please make
sure that the assembly that contains this type is referenced. If this type
is a part of your development project, make sure that the project has been
successfully built."
Source="System.Design"
StackTrace:
at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.Error(IDesignerSerializationManager manager, String exceptionText, String helpLink)
at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeExpression(IDesignerSerializationManager
manager, String name, CodeExpression expression)
at
System.ComponentModel.Design.Serialization.CodeDomSerializer.DeserializeStatementToInstance(IDesignerSerializationManager manager, CodeStatement statement)
at
System.ComponentModel.Design.Serialization.CodeDomSerializer.Deserialize(IDesignerSerializationManager manager, Object codeObject)
at
IndexCardDesigner.DesignerLoader.PerformLoad(IDesignerSerializationManager
serializationManager) in O:\Visual Studio Projects\Docstore.NET\Index Card
Designer\IndexCardDesigner\DesignerHost\DesignerLoaderService.vb:line 211
at
System.ComponentModel.Design.Serialization.BasicDesignerLoader.BeginLoad(IDesignerLoaderHost host)
> Hi David,
>
[quoted text clipped - 35 lines]
> Get Secure! - www.microsoft.com/security
> This posting is provided "as is" with no warranties and confers no rights.
"Jeffrey Tan[MSFT]" - 26 Sep 2005 07:38 GMT
Hi David,
Thanks for your feedback.
Because I did not have your source code and without reproduce your problem,
I can not give very useful hint to this exception. Also, in the exception
call stack, I do not know what does these symbols mean:
CodeDomSerializerBase
CodeDomSerializer.DeserializeStatementToInstance
Normally, these are not .Net BCL classes/methods(I can not see these
symbols in reflector).
Based on my research in the with Reflector, VS.net IDE already implemented
several CodeDomSerializer for us, such as RootCodeDomSerializer,
ControlCodeDomSerializer, ComponentCodeDomSerializer etc..
Usually, we invoked RootCodeDomSerializer.Deserialize method first, then it
internally invoke loop through the parameter collection we passed to it and
invoke corresponding child
ControlCodeDomSerializer/ComponentCodeDomSerializer for us. So the entire
Code dom is parsed and added to the designer by it.
RootCodeDomSerializer.Deserialize requires we pass CodeTypeReference type
for the second parameter. So I think we should manually use CodeDom classes
to parse the C#/VB.net code file into CodeTypeReference, then pass this
CodeTypeReference to the RootCodeDomSerializer.Deserialize.
Hope this helps.
Best regards,
Jeffrey Tan
Microsoft Online Partner Support

Signature
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.