Hi,
I get StackOverflow when I return an InstanceDescriptor which represents a
constructor which takes it's own type as parameter. Could someone explain
why return new InstanceDescriptor(ci,new object[]{date}); causes
StackOverflow? Is it again going into the ConvertTo? Why?
Short code snippet:
if(destinationType == typeof(InstanceDescriptor))
{
ConstructorInfo ci = typeof(ExtendedDate).GetConstructor(new
Type[]{typeof(ExtendedDate)});
ExtendedDate date = (ExtendedDate) value;
return new InstanceDescriptor(ci,new object[]{date});
}
Full sample code:
public class Component1 : System.ComponentModel.Component
{
public Component1(System.ComponentModel.IContainer container)
{
container.Add(this);
}
public Component1(){}
private ExtendedDate _date;
public ExtendedDate ExtendedDate
{
get { return _date; }
set { _date = value; }
}
bool ShouldSerializeExtendedDate()
{
return true;
}
}
[TypeConverter(typeof(ExtendedDateTypeConverter))]
public class ExtendedDate
{
public ExtendedDate(ExtendedDate date)
{
}
}
internal sealed class ExtendedDateTypeConverter: 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(value is ExtendedDate)
{
if(destinationType == typeof(string))
return ((ExtendedDate)value).ToString();
else if(destinationType == typeof(InstanceDescriptor))
{
ConstructorInfo ci = typeof(ExtendedDate).GetConstructor(new
Type[]{typeof(ExtendedDate)});
ExtendedDate date = (ExtendedDate) value;
return new InstanceDescriptor(ci,new object[]{date});
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type
sourceType)
{
if(sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom (context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
if(value is string)
{
return new ExtendedDate(null);
}
return base.ConvertFrom (context, culture, value);
}
}
Marina - 02 Dec 2004 16:46 GMT
You can actually debug your code, and see where the overflow occurrs. Just
attach one instance of the IDE with the source project for this code to an
instance of the IDE trying to use your object.
> Hi,
>
[quoted text clipped - 90 lines]
> }
> }
LF - 05 Dec 2004 17:28 GMT
I know I can debug it through another instance of VS.NET.
system.dll!System.ComponentModel.TypeConverter.ConvertTo(System.Object
value = {TestApp.Test}, System.Type destinationType =
{"System.ComponentModel.Design.Serialization.InstanceDescriptor"}) + 0x17
bytes
system.design.dll!System.ComponentModel.Design.Serialization.InstanceDescriptorCodeDomSerializer.Serialize(System.ComponentModel.Design.Serialization.IDesignerSerializationManager
manager =
{Microsoft.VisualStudio.Designer.Serialization.VSDesignerLoader.VsCodeDomLoader},
System.Object value = {TestApp.Test}) + 0xdb bytes
system.design.dll!System.ComponentModel.Design.Serialization.CodeDomSerializer.SerializeToExpression
It's constantly trying to serialize. This is because I have a constructor
that takes the class type as parameter.
(i.e.: class Test { public Test(Test t){} }) You will not be able to use
this constructor with VS.NET designer and custom TypeConverter. It will go
into infinite recursion trying to convert the parameter or maybe it's a
limitation of designer.
> You can actually debug your code, and see where the overflow occurrs. Just
> attach one instance of the IDE with the source project for this code to an
[quoted text clipped - 95 lines]
>> }
>> }
Andrew Smith \(Infragistics\) - 05 Dec 2004 19:01 GMT
I'm not sure it's necessarily the case that an object cannot take something
of the same type to its constructor but at some point in the serialization,
you will need to use an instancedescriptor that does not contain something
of that type. With regards to your stack overflow, your initial code doesn't
make sense because its passing itself into its own constructor - notice that
you are passing "date" into the constructor of the InstanceDescriptor which
is supposed to describe how to create "date" (i.e. the value passed into the
convertto). Now if you think about it further, even if you were to pass in a
different ExtendedDate object instance, that object would have to be
serialized to an instance descriptor as well since .net needs to get to the
point that it has serialized the value as text in the initializecomponent so
at some point you would have to use a constructor that would take different
parameters.
>I know I can debug it through another instance of VS.NET.
>
[quoted text clipped - 121 lines]
>>> }
>>> }
LF - 05 Dec 2004 21:52 GMT
I just wrote that sample specifically to repro the problem. In real case I
had this:
class ExtendedDate
{
public ExtendedDate(DatePart){}
public DatePart DatePart
{
get { return _datePart; }
}
...
}
class DatePart
{
public DatePart(DatePart){}
...
}
...
if(destinationType == typeof(InstanceDescriptor))
{
ConstructorInfo ci = typeof(ExtendedDate).GetConstructor(new
Type[]{typeof(DatePart)});
ExtendedDate date = (ExtendedDate) value;
return new InstanceDescriptor(ci,new object[]{date.DatePart});
}
...
if(destinationType == typeof(InstanceDescriptor))
{
ConstructorInfo ci = typeof(DatePart).GetConstructor(new
Type[]{typeof(DatePart)});
DatePart date = (DatePart) value;
return new InstanceDescriptor(ci,new object[]{date});
}
Without providing custom TypeConverter for DatePart VS designer will not
serialize the ExtendedDate collection property that I exposed on my
component. So i created another constructor for DatePart that takes string
for parsing DatePart and now it works. But what I wanted to do is create
ExtendedDate from existing ExtendedDate's DatePart directly, but that will
cause StackOverFlow calling ConvertTo in recursion.
"Andrew Smith (Infragistics)" <productmanager@infragistics.com> wrote in
message news:uaJ1dzv2EHA.1192@tk2msftngp13.phx.gbl...
> I'm not sure it's necessarily the case that an object cannot take
> something of the same type to its constructor but at some point in the
[quoted text clipped - 136 lines]
>>>> }
>>>> }
Andrew Smith \(Infragistics\) - 06 Dec 2004 02:13 GMT
But your real case suffers from the same issue. You are trying to serialize
DatePart by passing the DatePart that is being serialized into its own
constructor.
i.e.
'in your code 'date' comes from the value passed into the ConvertTo method
and is therefore the object
'that vs is attempting to serialize
DatePart date = (DatePart) value;
'you're then creating an instancedescriptor, which is intended to tell vs
how to serialize a ctor call to create your type,
'by passing in the very instance that vs is asking you to serialize
return new InstanceDescriptor(ci,new object[]{date});
>I just wrote that sample specifically to repro the problem. In real case I
>had this:
[quoted text clipped - 183 lines]
>>>>> }
>>>>> }