Groups | Blog | Home
all groups > dotnet windows forms designtime > july 2004 >

dotnet windows forms designtime : Problems with IsupportInitialize and CodeDom


Dennes Torres
7/18/2004 6:48:34 PM
Hi !
I created a new component for my project. One of the properties of this
component is a collection of a class created by me, I called this class
"UmaTabela"

The class (each element in collection) has two properties, one of them is
another class, created by me. I called this class as "Mapeamento".

I used desinertimeserializationvisibility in collection property, and I
created a typeConverter to return instance descriptor for both, "UmaTabela"
class and "Mapeamento" class.

The problems started because "Mapeamento" class needs a initialization
sequence, so I implemented IsupportInitialize.

But VS didn't recognize the implementation of IsupportInitialize. VS
serialize the class and it's properties in the code, but didn't make the
calls for beginInit and endInit. I think this is because the class is inside
another class that's inside a collection.

To solve this problem I tried to create a custom codeDomSerializer to add
BeginInit and EndInit calls. After some trys the most closely I get is to
put the custom serializer in UmaTabela class. The problem is that Mapeamento
variable is created as a local variable inside initializeComponent and the
custom serializer generates a "me." keyword in front of method calls, like
this "me.mapeamento1.begininit", so this doesn't work because mapeamento1 is
local variable, not form variable.

So, some questions at this point :

A) Is there any other way to expose IsupportInitialize in this case without
create a custom codeDom serializer ? How to force this interface to be
regonized by VS ?

B) How to control if the components variables will be generated in form
level or in initializeComponent level ?

C) How to take out that "Me." keyword generated by the custom codeDom
serializer ?

P.S. : When Mapeamento class inherits from system.componentmodel.component
the "me." keyword appears. When it has no inheritance, "BeginInit" and
"EndInit" calls apears alone, with no object.

P.P.S : Sorry by my bad english and thanks a lot for help !

Some pieces of the code :

<TypeConverter(GetType(conversorMapeamento))> _
Public Class Mapeamento
Inherits System.ComponentModel.Component
Implements ISupportInitialize

.....

Public Sub BeginInit() Implements
System.ComponentModel.ISupportInitialize.BeginInit
...
End Sub

Public Sub EndInit() Implements
System.ComponentModel.ISupportInitialize.EndInit
...
End Sub
End Class

<TypeConverter(GetType(conversor)),
DesignerSerializer(GetType(MeuSerializer), GetType(CodeDomSerializer))> _
Public Class UmaTabela
Inherits System.ComponentModel.Component

....


<DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
Public Property TabelaOrigem() As IListSource
Get
Return (tb)
End Get
Set(ByVal Value As IListSource)
tb = Value
Mapeamento.TabelaOrigem = tb
End Set
End Property

<Editor(GetType(EditorMapeamento), GetType(UITypeEditor)),
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
Public Property Mapeamento() As Mapeamento
Get
Return (map)
End Get
Set(ByVal Value As Mapeamento)
map = Value
End Set
End Property
End Class

Public Class MeuSerializer
Inherits System.ComponentModel.Design.Serialization.CodeDomSerializer

Public Overrides Function Deserialize(ByVal manager As
System.ComponentModel.Design.Serialization.IDesignerSerializationManager,
ByVal codeObject As Object) As Object

End Function

Public Overrides Function Serialize(ByVal manager As
System.ComponentModel.Design.Serialization.IDesignerSerializationManager,
ByVal value As Object) As Object
Dim cd As CodeDomSerializer
Dim codeObject As CodeStatementCollection
Dim targetObject As CodeExpression
Dim inv As CodeMethodInvokeExpression
Dim novaColecao As New CodeStatementCollection
Dim cs As CodeStatement
Dim o As Object

If IsNothing(value) Then
Exit Function
End If

cd = manager.GetSerializer(GetType(UmaTabela).BaseType,
GetType(CodeDomSerializer))
o = cd.Serialize(manager, value)

If TypeOf o Is CodeStatementCollection Then

codeObject = o
Else
codeObject = New CodeStatementCollection
If Not IsNothing(o) Then
If TypeOf o Is CodeExpression Then
codeObject.Add(DirectCast(o, CodeExpression))
Else
codeObject.Add(DirectCast(o, CodeStatement))
End If
End If
End If

targetObject = MyBase.SerializeToReferenceExpression(manager,
DirectCast(value, UmaTabela).Mapeamento)

inv = New CodeMethodInvokeExpression(targetObject, "BeginInit")

novaColecao.Add(inv)

Dim i As Integer
For i = 0 To codeObject.Count - 1
novaColecao.Add(codeObject(i))
Next

novaColecao.Add(New CodeMethodInvokeExpression(targetObject,
"EndInit"))
Return (novaColecao)

End Function
End Class


draiko NO[at]SPAM rhenus.de
7/21/2004 1:27:47 AM
Hi Dennes,

The ISupportInitialize is (as far, as i see) recognized only when
implemented by components.

Wouldn't it be easyer (to solve the problem) to implement
the interface in the component that owns the collection, call
in EndInit() a method implemented in the collection, that iterates
through all members calling their initialization methods.

Another possibility is to override OnInsert() and OnSet() methods
of the collection itself initializing each member in the moment
when it adds.

The differences between these two approaches are obvious:

(i) when called in OnInsert/OnSet, initializing code will run
not only for deserialized members, but for all ones (== including
new members as they add in design mode and at runtime);

(ii) When initializing from EndInit() you can collect and prepare all
parameters you need. In OnInsert/OnSet methods you can access only
the new member and variables defined in the collection (and all
static fields of any class, of course). So, all values/pointers
you need must be passed to the collection (before the first member
adds) and saved there.
Usually it is enough to have a pointer to the owner control to get
all information the member initializer needs, but it depends.

Be aware: properties deserialization in InitializeComponent() is
ordered alphabelically. At the moment when members are deserialized and
add to collection, not all other properties are already set.

(iii) Initialization in in OnInsert/OnSet is done before the next
meber adds; Initialization called from EndInit is done when the whole
collection is already there. Look, what is better in your situation.

Regards,
Dima.

[quoted text, click to view]
AddThis Social Bookmark Button