ncupper / protobuf-net

Automatically exported from code.google.com/p/protobuf-net
Other
0 stars 0 forks source link

Serializing an array using the generic Type serialization, with partial solution #283

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
I needed to build a service who works as layer between me and Azure. So what I 
actually did was to send serialized documents and/or serialized data through 
this service to store them in the cloud and give me back when needed. The base 
idea is pretty simple, I made a ProtoRequest who has mainly these 2 properties:

[ProtoMember(4, DynamicType = true)]
public Type[] ParameterTypes { get; protected set; }

[ProtoMember(3, DynamicType = true)]
public object[] ParameterValues { get; protected set; }

So, one of the task I needed to implement is to send a sequence of values 
associated with a type.
In this specific not-working example I send 4 strings and an array of strings. 
So I have 5 ParameterTypes (string, string, string, string, string[]), and 5 
parameter values.

What is the expected output? What do you see instead?
It crashes with a ProtoExceptions who said it is unable to create type 
System.String[].

What version of the product are you using? On what operating system?
The r490 from SVN. I'm on Windows 7 and I work with .NET framework 4.0.

Please provide any additional information below.
I needed to find out a fast solution for my issues, so I wrote some temporary 
code (as described below) to workaround this issue. The only problem I have now 
is when I try to pass null to the array. In my example, instead of 5 parameter 
values, it returns me just 4.
Another problem happens when I pass as parameter value an empty array.
I worked around this on my code just passing an array just containing an empty 
string, but obviously it's not the optimal solution.

In the class BclHelpers, method ReadNetObject, in the case FieldObject inside 
the try/catch of the first if clause (row 410) I needed to check if type is an 
array, and using an appropriate activator to instance it, in this way:

if (type.IsArray)
{
    var arrayType = type.GetElementType();

    if (arrayType != null)
        value = Array.CreateInstance(arrayType, 0);
    else source.SkipField();
}
else
{
    value = ((options & NetObjectOptions.UseConstructor) == 0)
                ? BclHelpers.GetUninitializedObject(type)
                : Activator.CreateInstance(type);
}

In the method TryDeserializeList of Meta/TypeModel, I needed to slightly modify 
the second if clause (row 720) inside the loop. I needed to invert the if/else, 
so it became:

if (arraySurrogate != null)
{
    arraySurrogate.Add(nextItem);
}
else if (list != null)
{
    list.Add(nextItem);
}
else
{
    args[0] = nextItem;
    addMethod.Invoke(value, args);
}

Cause the typecast at row 708 caused the condition to be true, and tried to add 
a new element in a base-fixed collection.

Original issue reported on code.google.com by m.vitt...@gmail.com on 29 Mar 2012 at 10:35