Problem with Marshal.load in Silverlight

I’ve run into a problem when using Marshal.load in Silverlight - the
following exception is thrown:

NotSupportedException: Class IronRuby.Builtins.RubyObject does not have
a
valid deserializing constructor

I tracked the code down to RubyUtils.CreateObject(RubyClass/!/
theclass,
IEnumerable<KeyValuePair<string, object>>/!/ attributes). I see that
CreateObject will always throw in Silverlight when the type is
assignable
from ISerializable:

//------------------------------
public static object/!/ CreateObject(RubyClass/!/ theclass,
IEnumerable<KeyValuePair<string, object>>/!/ attributes) {
Assert.NotNull(theclass, attributes);

        Type baseType = theclass.GetUnderlyingSystemType();
        object obj;
        if (typeof(ISerializable).IsAssignableFrom(baseType)) {

#if !SILVERLIGHT // serialization
BindingFlags bindingFlags = BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Instance;
ConstructorInfo ci =
baseType.GetConstructor(bindingFlags,
null, _serializableTypeSignature, null);
if (ci == null) {
#endif
string message = String.Format(“Class {0} does not have
a
valid deserializing constructor”, baseType.FullName);
throw new NotSupportedException(message);
#if !SILVERLIGHT // serialization
}
SerializationInfo info = new SerializationInfo(baseType,
new
FormatterConverter());
info.AddValue(SerializationInfoClassKey, theclass);
foreach (var pair in attributes) {
info.AddValue(pair.Key, pair.Value);
}
obj = ci.Invoke(new object[2] { info, new
StreamingContext(StreamingContextStates.Other, theclass) });
#endif
} else {
obj = CreateObject(theclass);
foreach (var pair in attributes) {
theclass.Context.SetInstanceVariable(obj, pair.Key,
pair.Value);
}
}
return obj;
}
//------------------------------

Is this a bug, perhaps? I’d love to step through the code and find for
myself, but I can’t seem to build IronRuby using the Silverlight3 and
Silverlight4 build configurations (I get a ton of errors - any help
getting
it to build would rock!).

-Charles

Alright, I know I’m not supposed to send in patch’s for the runtime,
but
this is a bug in the Silverlight build. Classes implemented in Ruby
cannot
be created using RubyUtils.CreateObject, as I mentioned in my previous
email. As a result, Marshal.load will fail when trying to deserialize
classes implemented in Ruby, because the _underlyingSystemType will
be RubyObject, which implements ISerializable. In the debugger, if I
force
the aforementioned CreateObject method to call the
CreateObject(RubyClass/!/ theClass) overload, it works just fine.

We probably need to change this:
if (typeof(ISerializable).IsAssignableFrom(baseType)) {

to this:
if (typeof(ISerializable).IsAssignableFrom(baseType) && !(baseType is
RubyObject)) {

Should I make this change to my fork? Or would one of you core dev’s
make
the appropriate change for us (Tomas :p)?

P.S.

Would there be any interest in being able to mspec the Silverlight
build? I
would bet that would make catching these little bugs much easier. I
could
throw something together if it would help - something like a command
line
app called slmspec.

Thanks,

-Charles

On Sun, Jul 25, 2010 at 4:25 AM, Charles S. <

Filed a bug: http://ironruby.codeplex.com/workitem/4946

Jimmy has something almost ready for running tests on Silverlight.

Tomas

From: [email protected]
[mailto:[email protected]] On Behalf Of Charles
Strahan
Sent: Monday, July 26, 2010 6:26 PM
To: [email protected]
Subject: Re: [Ironruby-core] Problem with Marshal.load in Silverlight

Alright, I know I’m not supposed to send in patch’s for the runtime, but
this is a bug in the Silverlight build. Classes implemented in Ruby
cannot be created using RubyUtils.CreateObject, as I mentioned in my
previous email. As a result, Marshal.load will fail when trying to
deserialize classes implemented in Ruby, because the
_underlyingSystemType will be RubyObject, which implements
ISerializable. In the debugger, if I force the aforementioned
CreateObject method to call the CreateObject(RubyClass/!/ theClass)
overload, it works just fine.

We probably need to change this:
if (typeof(ISerializable).IsAssignableFrom(baseType)) {

to this:
if (typeof(ISerializable).IsAssignableFrom(baseType) && !(baseType is
RubyObject)) {

Should I make this change to my fork? Or would one of you core dev’s
make the appropriate change for us (Tomas :p)?

P.S.

Would there be any interest in being able to mspec the Silverlight
build? I would bet that would make catching these little bugs much
easier. I could throw something together if it would help - something
like a command line app called slmspec.

Thanks,

-Charles

On Sun, Jul 25, 2010 at 4:25 AM, Charles S.
<[email protected]mailto:[email protected]> wrote:
I’ve run into a problem when using Marshal.load in Silverlight - the
following exception is thrown:

NotSupportedException: Class IronRuby.Builtins.RubyObject does not have
a valid deserializing constructor

I tracked the code down to RubyUtils.CreateObject(RubyClass/!/
theclass, IEnumerable<KeyValuePair<string, object>>/!/ attributes). I
see that CreateObject will always throw in Silverlight when the type is
assignable from ISerializable:

//------------------------------
public static object/!/ CreateObject(RubyClass/!/ theclass,
IEnumerable<KeyValuePair<string, object>>/!/ attributes) {
Assert.NotNull(theclass, attributes);

        Type baseType = theclass.GetUnderlyingSystemType();
        object obj;
        if (typeof(ISerializable).IsAssignableFrom(baseType)) {

#if !SILVERLIGHT // serialization
BindingFlags bindingFlags = BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Instance;
ConstructorInfo ci =
baseType.GetConstructor(bindingFlags, null, _serializableTypeSignature,
null);
if (ci == null) {
#endif
string message = String.Format(“Class {0} does not have
a valid deserializing constructor”, baseType.FullName);
throw new NotSupportedException(message);
#if !SILVERLIGHT // serialization
}
SerializationInfo info = new SerializationInfo(baseType,
new FormatterConverter());
info.AddValue(SerializationInfoClassKey, theclass);
foreach (var pair in attributes) {
info.AddValue(pair.Key, pair.Value);
}
obj = ci.Invoke(new object[2] { info, new
StreamingContext(StreamingContextStates.Other, theclass) });
#endif
} else {
obj = CreateObject(theclass);
foreach (var pair in attributes) {
theclass.Context.SetInstanceVariable(obj, pair.Key,
pair.Value);
}
}
return obj;
}
//------------------------------

Is this a bug, perhaps? I’d love to step through the code and find for
myself, but I can’t seem to build IronRuby using the Silverlight3 and
Silverlight4 build configurations (I get a ton of errors - any help
getting it to build would rock!).

-Charles

Excellent - thanks Tomas!

-Charles

On Mon, Jul 26, 2010 at 8:40 PM, Tomas M. <

D’oh! I didn’t test that code snippet - sorry.

It should probably be something more along the lines of
if (typeof(ISerializable).IsAssignableFrom(baseType) &&
!!typeof(RubyObject).IsAssignableFrom(baseType)) {

or

if (typeof(ISerializable).IsAssignableFrom(baseType) && !(baseType ==
typeof(RubyObject))) {

-Charles
On Mon, Jul 26, 2010 at 8:26 PM, Charles S. <