Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Windows Forms / Design Time / October 2006

Tip: Looking for answers? Try searching our database.

IExtender Collection property Serialization problems

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Mick Doherty - 09 Oct 2006 12:45 GMT
I have recently been playing with IExtenderProvider trying to implement a
Collection Property and came upon this curious scenario:

If I set up a property to return a Componet Array the code is correctly
serialized as follows:
\\\
this.foo1.SetBar(this.button1, new FooBarExtension.FooBar[] {
                this.fooBar1});
///

If, however, I change the return type to a Collection the property is
incorrectly serialized like this:
\\\
this.button1.BarCollection.AddRange(new FooBarExtension.FooBar[]{
                this.fooBar2});
///

Manually correcting it as follows has the desired effect:
\\\
this.foo1.SetBarCollection(this.button1,
   new FooBarExtension.FooBarCollection(new FooBarExtension.FooBar[]
                {this.fooBar2}));
///
... but if I then change the items it is once again serialized incorrectly.

Can anyone offer an explanation of this as it has been driving me nuts?

The code used in this test follows:
\\\
using System.Windows.Forms;
using System.Globalization;
using System.Reflection;
using System.ComponentModel.Design.Serialization;

namespace FooBarExtension
{
   [ProvideProperty("Bar",typeof(Control))]
   [ProvideProperty("BarCollection",typeof(Control))]
   public class Foo : System.ComponentModel.Component, IExtenderProvider
   {
       private System.ComponentModel.Container components = null;
       public Foo(System.ComponentModel.IContainer container)
       {
           container.Add(this);
           InitializeComponent();
       }
       public Foo()
       {
           InitializeComponent();
       }
       protected override void Dispose( bool disposing )
       {
           if( disposing )
           {
               if(components != null)
               {
                   components.Dispose();
               }
           }
           base.Dispose( disposing );
       }
       #region Component Designer generated code
       private void InitializeComponent()
       {
           components = new System.ComponentModel.Container();
       }
       #endregion
       bool IExtenderProvider.CanExtend(object extendee)
       {
           return extendee is Control;
       }
       private Hashtable bar = new Hashtable();
       private Hashtable barCollection = new Hashtable();
       public FooBar[] GetBar(object extendee)
       {
           if (bar.Contains(extendee))
               return (FooBar[])bar[extendee];
           return new FooBar[]{};
       }
       public void SetBar(object extendee, FooBar[] value)
       {
           if (bar.Contains(extendee))
               bar.Remove(extendee);
           bar.Add(extendee, value);
       }
       [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
       public FooBarCollection GetBarCollection(object extendee)
       {
           if (barCollection.Contains(extendee))
               return (FooBarCollection)barCollection[extendee];
           FooBarCollection fbc = new FooBarCollection();
           barCollection.Add(extendee, fbc);
           return fbc;
       }
       public void SetBarCollection(object extendee, FooBarCollection
value)
       {
           if (barCollection.Contains(extendee))
               barCollection.Remove(extendee);
           barCollection.Add(extendee, value);
       }
   }

   [DesignTimeVisible(false)]
   public class FooBar : Component
   {
       public FooBar(){}
       public FooBar(string text) : this()
       {
           this.text=text;
       }
       private string text = "";
       public string Text
       {
           get{return this.text;}
           set{this.text = value;}
       }
       public bool ShouldSerializeText()
       {
           return this.text != "";
       }
   }

   public class FooBarCollection : CollectionBase
   {
       public FooBarCollection() : base(){}
       public FooBarCollection(FooBar[] items) : this()
       {
           this.InnerList.AddRange(items);
       }
       public int Add(FooBar item)
       {
           return this.InnerList.Add(item);
       }
       public void AddRange(FooBar[] items)
       {
           this.InnerList.AddRange(items);
       }
       public void AddRange(FooBarCollection items)
       {
           this.InnerList.AddRange(items);
       }
       public void Remove(FooBar item)
       {
           this.InnerList.Remove(item);
       }
       public FooBar this[int index]
       {
           get{return this[index];}
       }
   }
}
///

Signature

Mick Doherty
http://dotnetrix.co.uk/nothing.html

Frank Hileman - 15 Oct 2006 18:58 GMT
Hi Mick,

You should change
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

As long as it is set to Content, it will try to use Add or AddRange.

Regards,
Frank Hileman

check out VG.net: http://www.vgdotnet.com
Animated vector graphics system
Integrated Visual Studio graphics editor

>I have recently been playing with IExtenderProvider trying to implement a
>Collection Property and came upon this curious scenario:
[quoted text clipped - 151 lines]
> }
> ///
Mick Doherty - 17 Oct 2006 16:09 GMT
Hi Frank,

I had thought about that and played with a custom serializer for the
Collection class, but could not get a reference to the extender. I've not
really worked with CodeDomSerializers and have found very little useful info
on them.

I guess this is one of those things that's going to bug me for a while.

Signature

Mick Doherty
http://dotnetrix.co.uk/nothing.html

> Hi Mick,
>
[quoted text clipped - 165 lines]
>> }
>> ///
Frank Hileman - 18 Oct 2006 18:18 GMT
Hi Mick,

I was referring to the attribute on GetBarCollection, which I thought was
your code. That attribute is probably triggering the serialization behavior.

If you can avoid a custom serializer, I recommend that. Another thing to be
aware of, perhaps this has been fixed, but in VS 2003 it would never
serialize correctly a collection implementing AddRange(<array of your data
type>), unless that collection was used for IComponent (sited) objects.
Non-IComponent collections would serialize correctly just implementing
Add(<your data type). This is unrelated to your other problem which I think
is just the Content attribute setting.

- Frank

> Hi Frank,
>
[quoted text clipped - 174 lines]
>>> }
>>> ///
Mick Doherty - 18 Oct 2006 19:52 GMT
HI Frank,

Without the
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
attribute the collection does not serialize at all. I am aware of non
IComponent based objects not serializing correctly and if you look closer,
you'll see that I made the Collection Items class (FooBar) inherit from
Component.

I did try not implementing the AddRange() method in the collection class,
but this made no difference at all. The problem is not wholly in the method
of serialization, but in the fact that the collection property of an
IExtenderProvider is serialized as a property of the object which is being
extended.

As far as I can tell, there is no way to fix my problem without writing a
custom serializer for the collection class, but for the moment this has got
the better of me.

I suppose the solution is just to use an Array instead of a Collection as
this does serialize correctly, but then you lose all the benefits of the
collection class.

I don't like to let these things get the better of me, and I shall fix it
one day, but I'll put it aside for now and concentrate on other problems.

Thanks for trying to help.

Signature

Mick Doherty
http://dotnetrix.co.uk/nothing.html

> Hi Mick,
>
[quoted text clipped - 191 lines]
>>>> }
>>>> ///
Frank Hileman - 19 Oct 2006 00:50 GMT
Hi Mick,

You can serialize non-IComponent classes in a collection, we do it with a
few collections in VG.net. But I have never tried an IExtenderProvider
provided collection, so probably you have hit some bugs specific to that.
The AddRange error I mentioned was only ever manifested for non-IComponent
types, and I think that is not related to your problem.

If you are serializing IComponent types, are they all sited correctly?
Non-sited IComponent objects (with no designer) will not serialize
correctly.

Frank

> HI Frank,
>
[quoted text clipped - 23 lines]
>
> Thanks for trying to help.
Mick Doherty - 19 Oct 2006 14:59 GMT
Hi Frank,

The Collection behaves exactly as expected if used as a property within a
Control. Obviously the code example that I gave is not complete, but it
should still work and for any class other than an IExtenderProvider, it
does.
The objects themselves are being correctly serialized. The Collection to
which the objects belong is being serialized, but it is being serialized
incorrectly. If I manually change the code to the correct CodeExpression,
then the IDE will be happy, but if I change the collection at any time then
the designers will rewrite the CodeExpression in an incorrect format.

This incorrect Serialization that I am seeing is very specific to
IExtenderProviders.

I have no trouble getting non IComponent based classes to Serialize, I just
add a TypeConvertor which returns an InstanceDescriptor and it generally
serializes just fine. The real class that I was working with, does not
implement IComponent. I reproduced a very basic example (I'm not really
creating a FooBar Extender) and for simplicity made the class to be used as
objects in the collection, Inherit from component. The result of this simple
example is exactly the same as the much more complex example that I was
working with.

Signature

Mick Doherty
http://dotnetrix.co.uk/nothing.html

> Hi Mick,
>
[quoted text clipped - 37 lines]
>>
>> Thanks for trying to help.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.