Serializing Collections to Code

  • Thread starter Thread starter Mark Olbert
  • Start date Start date
M

Mark Olbert

I'm trying to get a CollectionBase property to serialize properly into the IntializeComponent()
call.

My understanding is that I have to:

1) implement a TypeConverter that can return an InstanceDescriptor that describes how to create the
objects that are in the collection;

2) mark the property as being "content" serializable, and using the custom TypeConverter

3) perhaps also include the Reset<myprop> and ShouldSerialize<myprop> methods as well

I've done all this, and the blasted thing still doesn't work:

the component property stuff:

[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
NotifyParentProperty(true),
TypeConverter(typeof(SelectCmdConverter)),
]
public SelectCmdList SelectCmds
{
get
{
if( selectCmds == null )
selectCmds = new SelectCmdList();
return selectCmds;
}
}

// I use this because lazy instantiation makes setting the property from the Designer a pain in the
// butt
internal void SetSelectCmds( SelectCmdList aList )
{
selectCmds = aList;
}

private void ResetSelectCmds()
{
selectCmds = null;
}

private bool ShouldSerializeSelectCmds()
{
// obviously overkill
return true;
}

The custom TypeConverter (translated from a VB.NET Dr GUI example I found): NOTE -- none of these
methods ever get called

public class SelectCmdConverter : TypeConverter
{
public override bool CanConvertTo( ITypeDescriptorContext context, Type destinationType )
{
if( destinationType == typeof(InstanceDescriptor) )
return true;

return base.CanConvertTo(context, destinationType);
}

public override object ConvertTo( ITypeDescriptorContext context, System.Globalization.CultureInfo
culture, object value, Type destinationType )
{
if( destinationType == typeof(InstanceDescriptor) )
{
SelectCmd theCmd = (SelectCmd) value;

ConstructorInfo cmdCtor = typeof(SelectCmd).GetConstructor(new Type[] {
typeof(string), typeof(string) });
string[] argList = new string[] { theCmd.Table, theCmd.SelectCommand };

return new InstanceDescriptor(cmdCtor, argList);
}

return base.ConvertTo (context, culture, value, destinationType);
}
}

An excerpt from my custom componentdesigner, where I try to make darn sure someone :) knows the
SelectCmdList has changed:

IComponentChangeService chgSvc = (IComponentChangeService)
Component.Site.GetService(typeof(IComponentChangeService));

PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(Component);
SqlDataPackage thePkg = (SqlDataPackage) Component;
chgSvc.OnComponentChanging(Component, properties["SelectCmds"]);
thePkg.SetSelectCmds(selectCmds);
chgSvc.OnComponentChanged(Component, properties["SelectCmds"], thePkg.SelectCmds, selectCmds);

I can see the ShouldSerialize... method get called in the debugger, and the .cs file where my
component is "sited" gets marked as changed (i.e., the IDE rewrote the InitializeComponent()
method), but there are no references to the SelectCmdList property being initialized!

Any tips or suggestions would be MOST appreciated.

- Mark
 
Okay, I'm a nitwit: the problem was that I applied the SelectCmdConverter TypeConverter attribute
to the >>SelectCmdList<<, not the SelectCmd class definition itself.

Fixing that resulted in the serialization working correctly.

- Mark
 
Back
Top