473,394 Members | 1,714 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

SerializationSurrogate problem with Arrays

Can someone please help me and tell my why the following code is not
working, and hopefully how to get it working?

What I am trying to do is make a serialization surrogate that stores,
amongst other things, and array of objects that are also serialised by
the same surrogate. It serializes alright, but when it comes to
deserialization, the array comes out as an array (correct length) of
nulls. grrr... I'm pulling my hair out!!

Any help really appreciated.

Cheers
Greg

------ CODE START HERE ------
using System;
using System.Collections;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace SerializationSurrogateTest
{
public class Parent

{
private string _name;

public string Name { get { return _name; } set { _name = value; } }
private ArrayList _children;
public ArrayList Children { get { return _children; } }
public Parent()
{
_children = new ArrayList();
}
public override string ToString()

{
return Name;
}
}
public class Child

{
private string _name;

public string Name { get { return _name; } set { _name = value; } }
public Child()
{

}
public override string ToString()

{
return Name;
}
}
public class Surrogate : ISerializationSurrogate

{
#region ISerializationSurrogate Members
public void GetObjectData(object obj, SerializationInfo info,
StreamingContext context)
{
if( obj is Parent )

{
info.AddValue( "children", (Child[])((Parent)obj).Children.ToArray(
typeof( Child ) ), typeof( Child[] ) );
info.AddValue( "name", ((Parent)obj).Name );

}
else if( obj is Child )

{
info.AddValue( "name", ((Child)obj).Name );

}
Console.WriteLine( "Serializing {0}: {1}", obj.GetType().Name,
obj.ToString() );
}
public object SetObjectData(object obj, SerializationInfo info,
StreamingContext context, ISurrogateSelector selector)

{
if( obj is Parent )

{
//object c = info.GetValue( "children", typeof( object[] ) );
Child[] children = (Child[])info.GetValue( "children", typeof(
Child[] ) );
((Parent)obj).Children.Clear();
((Parent)obj).Children.AddRange( children );
((Parent)obj).Name = (string)info.GetValue( "name", typeof( object
) );

}
else if( obj is Child )

{
((Child)obj).Name = (string)info.GetValue( "name", typeof( object )
);
}
Console.WriteLine( "Deserializing {0}: {1}", obj.GetType().Name,
obj.ToString() );
return obj;
}
#endregion
}
/// <summary>
/// Summary description for StartHere.
/// </summary>
public class StartHere

{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()

{
Child child1 = new Child();
child1.Name = "Child1";
Child child2 = new Child();
child2.Name = "Child2";
Parent parent = new Parent();
parent.Name = "Parent1";
parent.Children.Add( child1 );
parent.Children.Add( child2 );

SurrogateSelector selector = new SurrogateSelector();
selector.AddSurrogate( typeof( Parent ),
new StreamingContext( StreamingContextStates.All ),
new Surrogate() );
selector.AddSurrogate( typeof( Child ),
new StreamingContext( StreamingContextStates.All ),
new Surrogate() );
MemoryStream stream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.SurrogateSelector = selector;
formatter.Serialize( stream, parent );
stream.Position = 0;
object result = formatter.Deserialize( stream );
}
}

}

Nov 16 '05 #1
10 2855
You are getting whacked by the intricacies of serialization. Your parent object
isn't constructed. It is blitted into memory directly. That means your
collections
are nulled out and aren't being set to a new ArrayList... I'd recommend writing
your parent as follows so that a new array-list is constructed upon access.

public class Parent {
private string _name;
public string Name { get { return _name; } set { _name = value; } }
private ArrayList _children;

public ArrayList Children {
get {
if ( _children == null ) {
_children = new ArrayList();
}

return _children;
}
}

public override string ToString() {
return Name;

}
}
--
Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

"gregbacchus" <gr*********@hotmail.com> wrote in message
news:11*********************@z14g2000cwz.googlegro ups.com...
Can someone please help me and tell my why the following code is not
working, and hopefully how to get it working?

What I am trying to do is make a serialization surrogate that stores,
amongst other things, and array of objects that are also serialised by
the same surrogate. It serializes alright, but when it comes to
deserialization, the array comes out as an array (correct length) of
nulls. grrr... I'm pulling my hair out!!

Any help really appreciated.

Cheers
Greg

------ CODE START HERE ------
using System;
using System.Collections;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace SerializationSurrogateTest
{
public class Parent

{
private string _name;

public string Name { get { return _name; } set { _name = value; } }
private ArrayList _children;
public ArrayList Children { get { return _children; } }
public Parent()
{
_children = new ArrayList();
}
public override string ToString()

{
return Name;
}
}
public class Child

{
private string _name;

public string Name { get { return _name; } set { _name = value; } }
public Child()
{

}
public override string ToString()

{
return Name;
}
}
public class Surrogate : ISerializationSurrogate

{
#region ISerializationSurrogate Members
public void GetObjectData(object obj, SerializationInfo info,
StreamingContext context)
{
if( obj is Parent )

{
info.AddValue( "children", (Child[])((Parent)obj).Children.ToArray(
typeof( Child ) ), typeof( Child[] ) );
info.AddValue( "name", ((Parent)obj).Name );

}
else if( obj is Child )

{
info.AddValue( "name", ((Child)obj).Name );

}
Console.WriteLine( "Serializing {0}: {1}", obj.GetType().Name,
obj.ToString() );
}
public object SetObjectData(object obj, SerializationInfo info,
StreamingContext context, ISurrogateSelector selector)

{
if( obj is Parent )

{
//object c = info.GetValue( "children", typeof( object[] ) );
Child[] children = (Child[])info.GetValue( "children", typeof(
Child[] ) );
((Parent)obj).Children.Clear();
((Parent)obj).Children.AddRange( children );
((Parent)obj).Name = (string)info.GetValue( "name", typeof( object
) );

}
else if( obj is Child )

{
((Child)obj).Name = (string)info.GetValue( "name", typeof( object )
);
}
Console.WriteLine( "Deserializing {0}: {1}", obj.GetType().Name,
obj.ToString() );
return obj;
}
#endregion
}
/// <summary>
/// Summary description for StartHere.
/// </summary>
public class StartHere

{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()

{
Child child1 = new Child();
child1.Name = "Child1";
Child child2 = new Child();
child2.Name = "Child2";
Parent parent = new Parent();
parent.Name = "Parent1";
parent.Children.Add( child1 );
parent.Children.Add( child2 );

SurrogateSelector selector = new SurrogateSelector();
selector.AddSurrogate( typeof( Parent ),
new StreamingContext( StreamingContextStates.All ),
new Surrogate() );
selector.AddSurrogate( typeof( Child ),
new StreamingContext( StreamingContextStates.All ),
new Surrogate() );
MemoryStream stream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.SurrogateSelector = selector;
formatter.Serialize( stream, parent );
stream.Position = 0;
object result = formatter.Deserialize( stream );
}
}

}

Nov 16 '05 #2
Thanks for you reply Justin, but this is another issue all together.
One which I already fixed (just didn't show in this code) by calling
the default constructor explicity - as shown below. My actual problem
is that
info.GetValue( "children", typeof( ArrayList ) )
comes back as an arraylist of nulls.

Greg
public object SetObjectData(object obj, SerializationInfo info,
StreamingContext context, ISurrogateSelector selector)
{
ConstructorInfo constructor = obj.GetType().GetConstructor( new
Type[0] );
obj = constructor.Invoke( new object[0] );
....

Nov 16 '05 #3
Using the code I'm about to paste below, which is just your code with
the parent change the serialization is clearly working based on the last
two writeline calls.

using System;
using System.Collections;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace SerializationSurrogateTest {
public class Parent {
private string _name;
public string Name { get { return _name; } set { _name = value; } }
private ArrayList _children;

public ArrayList Children {
get {
if ( _children == null ) {
_children = new ArrayList();
}

return _children;
}
}

public override string ToString() {
return Name;

}
}
public class Child
{
private string _name;

public string Name { get { return _name; } set { _name = value; } }
public Child()
{

}
public override string ToString()

{
return Name;
}
}
public class Surrogate : ISerializationSurrogate {
public void GetObjectData(object obj, SerializationInfo info,
StreamingContext context) {
if( obj is Parent ) {
info.AddValue( "children",
(Child[])((Parent)obj).Children.ToArray(typeof( Child ) ), typeof( Child[] ) );
info.AddValue( "name", ((Parent)obj).Name );
} else if( obj is Child ) {
info.AddValue( "name", ((Child)obj).Name );
}
Console.WriteLine( "Serializing {0}: {1}", obj.GetType().Name,
obj.ToString() );
}

public object SetObjectData(object obj, SerializationInfo info,
StreamingContext context, ISurrogateSelector selector) {
if( obj is Parent ) {
//object c = info.GetValue( "children", typeof( object[] ) );
Child[] children = (Child[])info.GetValue( "children",
typeof(Child[] ) );
((Parent)obj).Children.Clear();
((Parent)obj).Children.AddRange( children );
((Parent)obj).Name = (string)info.GetValue( "name", typeof(
object) );

} else if( obj is Child ) {
((Child)obj).Name = (string)info.GetValue( "name", typeof(
object ) );

}

Console.WriteLine( "Deserializing {0}: {1}", obj.GetType().Name,
obj.ToString() );
return obj;
}
}
public class StartHere {
[STAThread]
private static void Main() {
Child child1 = new Child();
child1.Name = "Child1";

Child child2 = new Child();
child2.Name = "Child2";

Parent parent = new Parent();
parent.Name = "Parent1";

parent.Children.Add( child1 );
parent.Children.Add( child2 );

SurrogateSelector selector = new SurrogateSelector();
selector.AddSurrogate( typeof( Parent ), new StreamingContext(
StreamingContextStates.All ), new Surrogate() );
selector.AddSurrogate( typeof( Child ), new StreamingContext(
StreamingContextStates.All ), new Surrogate() );

MemoryStream stream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.SurrogateSelector = selector;
formatter.Serialize( stream, parent );
stream.Position = 0;
Parent result = (Parent) formatter.Deserialize( stream );

for(int i = 0; i < result.Children.Count; i++) {
Console.WriteLine(result.Children[i]);
}
}
}
}
--
Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

"Greg Bacchus" <gr*********@hotmail.com> wrote in message
news:11**********************@c13g2000cwb.googlegr oups.com...
Thanks for you reply Justin, but this is another issue all together.
One which I already fixed (just didn't show in this code) by calling
the default constructor explicity - as shown below. My actual problem
is that
info.GetValue( "children", typeof( ArrayList ) )
comes back as an arraylist of nulls.

Greg
public object SetObjectData(object obj, SerializationInfo info,
StreamingContext context, ISurrogateSelector selector)
{
ConstructorInfo constructor = obj.GetType().GetConstructor( new
Type[0] );
obj = constructor.Invoke( new object[0] );
...

Nov 16 '05 #4
That doesn't work on either of my computers. I copied and pasted your
code exactly.
result.Children[i] is null for both of the entries.

Cheers
Greg

Nov 16 '05 #5
Interesting, then we have an impasse, I can't help unless I can repro your
situation exactly, and for me the code works... I'll play around a bit with
the code and see if I can get it to fail.

So with the code, you got two empty strings printed out instead of Child1 and
Child2?
--
Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

"Greg Bacchus" <gr*********@hotmail.com> wrote in message
news:11*********************@c13g2000cwb.googlegro ups.com...
That doesn't work on either of my computers. I copied and pasted your
code exactly.
result.Children[i] is null for both of the entries.

Cheers
Greg

Nov 16 '05 #6
yeah, and if i put a breakpoint in, the value is null... not even a
Child() object without the values set.
maybe a framework version issue??? I'm using v1.1.4322.573

Nov 16 '05 #7
I went back and ran it on V1.1 and I get your issue. Now that I have
a repro I'll try and work up a test case tonight and throw it on a Whidbey
build tomorrow. I think I've found your problem, but I'll have to drastically
rewrite your program to get things working properly...
--
Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

"Greg Bacchus" <gr*********@hotmail.com> wrote in message
news:11*********************@f14g2000cwb.googlegro ups.com...
yeah, and if i put a breakpoint in, the value is null... not even a
Child() object without the values set.
maybe a framework version issue??? I'm using v1.1.4322.573

Nov 16 '05 #8
You need to deserialize the collection or array, and then set it on the object
directly. That
way when your elements are created later they get set on the collection or array
that was
just deserialized.

This seems like a breaking change of some sort, but surrogates aren't widely
used.

--
Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

using System;
using System.Collections;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace SerializationSurrogateTest {
public class Parent {
private string _name;
public string Name { get { return _name; } set { _name = value; } }
private ArrayList _children;

public ArrayList Children {
get {
if ( _children == null ) {
_children = new ArrayList();
}

return _children;
}
set {
_children = value;
}
}

public override string ToString() {
return Name;

}
}
public class Child {
private string _name;

public string Name { get { return _name; } set { _name = value; } }

public override string ToString() {
return Name;
}
}
public class Surrogate : ISerializationSurrogate {
public void GetObjectData(object obj, SerializationInfo info,
StreamingContext context) {
if( obj is Parent ) {
info.AddValue( "children", ((Parent)obj).Children );
info.AddValue( "name", ((Parent)obj).Name );
} else if( obj is Child ) {
info.AddValue( "name", ((Child)obj).Name );
}
Console.WriteLine( "Serializing {0}: {1}", obj.GetType().Name,
obj.ToString() );
}

public object SetObjectData(object obj, SerializationInfo info,
StreamingContext context, ISurrogateSelector selector) {
if( obj is Parent ) {
//object c = info.GetValue( "children", typeof( object[] ) );
((Parent)obj).Children = ((ArrayList)info.GetValue( "children",
typeof(ArrayList) ));
((Parent)obj).Name = (string)info.GetValue( "name", typeof(
object) );

} else if( obj is Child ) {
((Child)obj).Name = (string)info.GetValue( "name", typeof(
object ) );

}

Console.WriteLine( "Deserializing {0}: {1}", obj.GetType().Name,
obj.ToString() );
return obj;
}
}
public class StartHere {
[STAThread]
private static void Main() {
Child child1 = new Child();
child1.Name = "Child1";

Child child2 = new Child();
child2.Name = "Child2";

Parent parent = new Parent();
parent.Name = "Parent1";

parent.Children.Add( child1 );
parent.Children.Add( child2 );

SurrogateSelector selector = new SurrogateSelector();
selector.AddSurrogate( typeof( Parent ), new StreamingContext(
StreamingContextStates.All ), new Surrogate() );
selector.AddSurrogate( typeof( Child ), new StreamingContext(
StreamingContextStates.All ), new Surrogate() );

MemoryStream stream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.SurrogateSelector = selector;
formatter.Serialize( stream, parent );
stream.Position = 0;
Parent result = (Parent) formatter.Deserialize( stream );

for(int i = 0; i < result.Children.Count; i++) {
Console.WriteLine(result.Children[i]);
}
}
}
}
Nov 16 '05 #9
Brilliant. Thanks for that... now I've got to try to figure out how to
fit that into my actual project, which is of course a bit more
complexed.

Nov 16 '05 #10
The changes you need to know are:

V1: Array members are instantiated during array creation
V1.1: Array members are instantiated after array creation

I'm not sure I'm 100% happy with how things work right now, and I'll fire off
some emails to find out why tomorrow morning.
--
Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

"Greg Bacchus" <gr*********@hotmail.com> wrote in message
news:11**********************@c13g2000cwb.googlegr oups.com...
Brilliant. Thanks for that... now I've got to try to figure out how to
fit that into my actual project, which is of course a bit more
complexed.

Nov 16 '05 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Dariusz | last post by:
I want to use arrays in my website (flat file for a guestbook), but despite having read through countless online tutorials on the topic, I just can't get my code to work. I know there are...
11
by: truckaxle | last post by:
I am trying to pass a slice from a larger 2-dimensional array to a function that will work on a smaller region of the array space. The code below is a distillation of what I am trying to...
5
by: jeremy targett | last post by:
Hello, in my program I use 2-dimensional arrays to hold two integer values for each of i members of a list. array holds a starting position, and array holds a label - in fact I #defined START as 0...
1
by: mdub317 | last post by:
I'm totally new to programming and I am wondering; when would be a good time to use an array or an indexer? I want to know what types of applications would make good use of arrays or indexers. ...
39
by: Martin Jørgensen | last post by:
Hi, I'm relatively new with C-programming and even though I've read about pointers and arrays many times, it's a topic that is a little confusing to me - at least at this moment: ---- 1)...
3
by: alcabo | last post by:
Hello, I'd like to improve several critical routines involving arrays (vectors and matrices)... How are arrays stored in memory? Row major or column major? (Like in C or like Fortran?)
29
by: Ancient_Hacker | last post by:
It sure would be nice if I could have a macro that add a level of indirection to its argument. So if I write: AddIndirection( X ) The macro AddIndirection will do: #define X (*X) ...
3
by: MariyaGel | last post by:
I have wrote the program and it worked fine until I had to include one more array into it. As you can see below the two arrays of volume and mass are working properly now I need to include a third...
19
by: Jim West | last post by:
The execution speed of the following code is dramatically faster if I declare some arrays globally rather than locally. That is FOO a, b, c; void bar() { ... } runs much faster (up to...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.