Topaz Filer - Email filing software
InitializeComponent() / How does it work?
Messages   Related Types
This message was discovered on microsoft.public.dotnet.framework.windowsforms.designtime.


Christian Benien
Hi there, I have a problem using the Designer/ComponentModel of the
..NET framework. The designer writes all the information relating to
the runtime use of a Component into the Components
InitializeComponent() function. The design time information goes into
a ressource file.

At first I was pretty sure that the Designer is actually calling the
InitializeComponent() function to set up all the property values. When
you change a property in the code it is reflected in the designer. If
you create a new Windows Forms application and add a Button to the
Form1 component, the InitializeComponent function is similar to

private void InitializeComponent()
{
...
this.button1.Text = "button1";
...
}

If you change "button1" to "OK" in the code view, the designer view
will show you a button with "OK" on it.

Our project is actually much bigger than this simple Windows Forms
example. We have our own implementation of the CodeDomSerializer which
generates the content of InitializeComponent(). Yet somewhere there is
a limit of what can be put into the function. Let's assume our
generated code looks similar to

private void InitializeComponent()
{
...
string s = "OK";
this.button1.Text = s;
...
}

What I would expect from the designer is the execution of
InitializeComponent() and setting button1.Text to "OK". This however
doesn't work. The Text property of button1 is not set at all,
defaulting to an empty string. Code following the statement in
question is executed.

This leads to the following conclusion and question:

The InitializeComponent() function is not executed at design time, but
instead parsed and interpreted. There are limits on what code is
allowed in InitializeComponent(). Does anyone know exactly what those
limits are? Or some way around them? Is this a bug or the expected
behaviour of the framework?
Reply to this message...
Vote that this is a GOOD answer...
 
New BootFX DBGet build available
Twitter and Snow… simple #uksnow
 
    
Frank Hileman
Hello,

Shawn Burke would be the one to answer your question. Are you delegating the
code serialization/deserailzation to the default codedomserializer, and
modifying the output? If not, this is what I recommend. Definitely you
cannot use flow of control constructs. Any values on the right hand side of
a property assignment need to be completely handled with your own
serialization/deseralization code if you want the regenerated code to be the
same as the input. That is, if you create a typeconverter, and instance
descriptors, for something on the right hand side, the
serialization/deserialization will work. But if you just do custom code dom
serialization, and don't write code to do the deserialization, your custom
code will be interpreted, and the results may not be what you want.

If you haven't read it here is the main article:

http://msdn.microsoft.com/library/dndotnet/html/custcodegen.asp

Regards,
Frank Hileman
Prodige Software Corporation

"Christian Benien" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer...
 
Windows 7 compatible tool for mounting ISO images
Introduction to BootFX’s Object Relational Mapping Functionality article now live on CodeProject
 
    
Christian Benien
Hello Frank,

thank you for pointing out this article, which I haven't read before.
Since I don't think I can solve my problem with TypeDescriptors, I
will look into writing my own deserializer. So far I only have a
custom CodeDom serializer very similar to the one in Shawn Burke's
article. It generates codelines that look like this:

this.MyObject1 = new MyObject();
this.MyObject2 = new MyObject();
....
this.MyObject1.SomeProperty = "whatever";
....
this.MyObject2.AddReference(this.MyObject1.SomeOtherProperty["SomeIdentifier"]);

SomeOtherProperty returns a Hashtable where I look up references to
other objects. This works great in runtime code, but cannot be
interpreted in design mode.

Christian
Reply to this message...
Vote that this is a GOOD answer...
 
 
    
Christian Benien
While trying to write a custom Deserializer I inserted some debug code
into it:

public override object Deserialize(IDesignerSerializationManager
manager, object codeObject)
{
System.IO.StringWriter sw = new System.IO.StringWriter();
Microsoft.CSharp.CSharpCodeProvider cscp =
new Microsoft.CSharp.CSharpCodeProvider();
System.CodeDom.Compiler.CodeGeneratorOptions options =
new System.CodeDom.Compiler.CodeGeneratorOptions();

System.CodeDom.Compiler.ICodeGenerator debugCode =
cscp.CreateGenerator();
if (codeObject is CodeStatement)
{
CodeStatement statement = codeObject as CodeStatement;
debugCode.GenerateCodeFromStatement(codeObject as
CodeStatement,sw,options);
}
else if (codeObject is CodeStatementCollection)
foreach (CodeStatement statement in
((CodeStatementCollection)codeObject))
{
debugCode.GenerateCodeFromStatement(statement,sw,options);
}
System.Windows.Forms.MessageBox.Show(sw.ToString());

return GetBaseSerializer(manager).Deserialize(manager,
codeObject);
}

codeObject contains only the code lines from the base serializer - my
custom generated code is not available. How am I supposed to write my
own deserializer when I don't get access to the code which I want to
deserialize?

Has anyone ever implemented a CodeDomSerialize.Deserialize method? How
does it work?
Reply to this message...
Vote that this is a GOOD answer...
 
Xenu Link Sleuth
Chromium OS – really?
 
    
Frank Hileman
You are generating code in the deserializer, and printing it. No Effect. The
code dom is not modified. You need to generate code dom objects in the
serialize, and interpret them in the deserialize. The code generator is not
what you need -- you only need code-dom objects (unless you need a custom
snippet).

Here is another example containing a serailizer:

http://www.gotdotnet.com/team/windowsforms/shapedesigner.aspx

"Christian Benien" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer...
 
Invocation Software – the new name for the makers of Topaz Filer
Agile Modeling
 
    
Christian Benien
I think I've narrowed down my problem to the following:

When I serialize code in the CodeDomSerializer, I can write everything
I want to, even stuff not associated with the object which I am
currently serializing. Now where does the code go in the
deserialization process? It is handled by the CodeDomSerializer
associated with the item in the code line. For example I can create a
function call like in the third codeline when I am serializing the
TextBox. The deserialization is not done by the TextBox deserializer,
because DoSomething is part of my RootComponent...

// is handled by the CodeDomSerializer for Button
this.button1.Text = "OK";

// is handled by the CodeDomSerializer for TextBox
this.textBox1.Text = "Type here";

// who handles this?
this.DoSomething();

One would expect that the last line is handled by the
CodeDomSerializer that is associated with the Component I'm designing
(IDesignerHost.RootComponent). The problem is: the
CodeDomSerializer.Serialize method is called for my RootComponent, but
the CodeDomSerializer.Deserialize method is NOT called for
RootComponent.

Any ideas on this? Or is the deserialization of the RootComponent
initialization in InitializeComponent() always done in some class
specified by the RootDesignerSerializerAttribute?
Reply to this message...
Vote that this is a GOOD answer...
 
 
    
Shawn Burke [MS]
this.DoSomething will be invoked on your base type. The Forms designer
regularly does this when calling SuspentLayout/ResumeLayout on the base form
and it's really no different than accessing any other property or method on
the base class.

That line of code will be handled by the default serializer for the
component in question -- in this case the RootCodeDomSerializer that Form
will get and that derives most of it's functionality from
ComponentCodeDomSerializer.

Deserialization is really just interpreting. For each line of code, we
build a tree based on the code and then use reflection to apply that code to
live objects.

So for "this.TextBox1.Text = "Foo"", we see this, which is the root
component. We look for a field called "TextBox1" and get it's value, which
is the TextBox. Then we look for a property on that called "Text" and set
the value that way. Same for methods.

Hope that helps.

"Christian Benien" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer...
 
Creating colourways for Web development
URL shortening as a service
 
    
Frank Hileman
I don't have a root component serialization example to try right now. Unless
there is some problem with your code, you may be right (need
RootDesignerSerializerAttribute). Unfortunately I have not been able to get
a complete example of how to write such a serializer. I think the problem
is, there is no public class to derive from, which can do most of the work
(it is private). So if you do such a serializer you have to rewrite the
whole enchilada.

Hello Shawn, can you help here? I cannot.

"Christian Benien" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer...
 
New BootFX DBGet build available
Twitter and Snow… simple #uksnow
 
 
Microsoft.CSharp.CSharpCodeProvider
System.CodeDom.CodeStatement
System.CodeDom.CodeStatementCollection
System.CodeDom.Compiler.CodeGeneratorOptions
System.CodeDom.Compiler.ICodeGenerator
System.ComponentModel.Design.IDesignerHost
System.ComponentModel.Design.Serialization.CodeDomSerializer
System.ComponentModel.Design.Serialization.IDesignerSerializationManager
System.ComponentModel.Design.Serialization.RootDesignerSerializerAttribute
System.IO.StringWriter
System.Web.UI.MobileControls.TextBox
System.Web.UI.WebControls.TextBox
System.Windows.Forms.MessageBox
System.Windows.Forms.TextBox




Ad
BootFX
Reliable and powerful .NET application framework.
Looking to invest in a major software project? Technical and commercial advice available here.
Other Helpful Sites
MBR 247
Topaz Filer
SharePoint Email Filing
Software Advisory Services
 
Copyright © AMX Software Ltd 2008-2010. Portions copyright © Matthew Baxter-Reynolds 2001-2010. All rights reserved.
Contact Us - Terms of Use - Privacy Policy - 4.0.30129.1734