Serializing Partial Classes (Datasets)

G

Guest

I have a dataset called Checklists created with the dataset designer giving
me Checklists.designer.cs It has a [Serializable()] attribute, i.e.,

[Serializable()]
public partial class Checklists {
....
}

In another file, ChecklistsExt.cs I have

public partial class Checklists{
public string var1;
protected decimal var2;
....
}

This is part of an ASP.NET app and I put an instance of Checklists in the
session data. I am using sqlserver as the state persistence manager.

When I attempt to retrieve the Checklists instance from the session data
after a round trip, all the tables etc that are managed by
Checklists.designer.cs are there, but the variables in "my" half of the
partial class have lost their value.

The designer generated code has a significant chunk of code in its
getObjectData() method and the deserialization protected constructor and that
is how it gets its stuff in and out of the serialized session data store.

I think that the problem is that if there was no custom serialization code,
normal .NET introspection would handle the whole thing for me. But that isn't
happening and I can't figure out the right way to hook into the designer's
de/serialization logic.

If I had created a derived class instead of using partial classes, I could
handle the problem easily by overriding the getObjectData and constructor
code, calling the base methods and then adding my own custom variable
management.

What's the right way to do this? A quick response would be VERY much
appreciated as it is holding up deployment at the client site.

Thx
Marc
 
J

Jialiang Ge [MSFT]

Hello Marc,

From your post, my understanding on this issue is: you wonder how to extend
a partial class generated with DataSet designer and serialize the
properties in the extension. If I'm off base, please feel free to let me
know.

First, I hope to let you know that our managed newsgroup is focused on
break fix issues that are neither urgent, nor complex. If the issue is
urgent to your business, it is recommended that you contact Microsoft
Customer Support Services (CSS) via telephone so that a dedicated Support
Professional can assist you in a more efficient manner. Please be advised
that contacting phone support will be a charged call. To obtain the phone
numbers for specific technology request please take a look at the web site
listed at:
http://support.microsoft.com/default.aspx?scid=fh;EN-US;PHONENUMBERS. If
you are outside the US please see http://support.microsoft.com for regional
support phone numbers.

According to your description, the class Checklists inherits from
global::System.Data.DataSet and is signed with Serializable attribute. As
the MSDN article "Object Serialization in .NET"
(http://msdn2.microsoft.com/en-us/library/ms973893.aspx) says:
Case1: If a class is signed with "[Serializable()]" attribute and does not
implement ISerializable interface, the Common Language Runtime (CLR)
manages how objects are laid out in memory and the .NET Framework provides
an automated serialization mechanism by using reflection.
Case 2: If a class is signed with "[Serializable()]" attribute and
implements ISerializable interface, it will use the GetObjectData method
and a special constructor to serialize or deserialize the object.

Because System.Data.DataSet implements ISerializable interface, our
situation should fit the case 2. That is to say, .NET framework will use
the GetObjectData method and the deserialization contructor to
serialize/deserialize the object.

In your post, you extend the Checklists class by adding another partial
class. Because the properties var1, var2 in the extension are not added
into GetObjectData and the special constructor which is generated by the
designer, they will be lost when we try to serialize or deserialize them.

Here are several approaches to workaround it:
#1. As you said, we can make a derived class in which we override the
GetObjectData() and the desrialization contructor.

#2. We can add a wrapper class for Checklists.
That is to say, we could create a class and add Checklists object, var1,
var2 as its properties. Then we claim the class as Serializable and
implements ISerializable interface. Var1, var2 and the Checklists object
are serialized/deserialized respectively in GetObjectData and the special
constructor. For instance:
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("var1", var1);
info.AddValue("var2", var2);
info.AddValue("Checklists", checklists, typeof(checklists));
}

For more information about .net Serialization, you may refer to Jeffrey
Richter's three articles in MSDN Magazine:
http://msdn.microsoft.com/msdnmag/issues/02/04/net/
http://msdn.microsoft.com/msdnmag/issues/02/07/net/default.aspx
http://msdn.microsoft.com/msdnmag/issues/02/09/net/

Please let me know if you have any other concerns, or need anything else.

Sincerely,
Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
For MSDN subscribers whose posts are left unanswered, please check this
document: http://blogs.msdn.com/msdnts/pages/postingAlias.aspx

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications. If you are using Outlook Express/Windows Mail, please make sure
you clear the check box "Tools/Options/Read: Get 300 headers at a time" to
see your reply promptly.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Jialiang,

That was an exceedingly high quality response. Thank you.

I had thought of both approaches, and was hoping that I had simply
overlooked the "right" solution. It seems to me that partial classes are
"broken" with respect to serialization. There is a similar problem in the
Windows Forms area with respect to dispose(), which is defined in the
designer and there is no way for the programmer to hook his/her code in.
Both partial classes and serialization are good ideas -- too bad you can't
use both at the same time.

It occurs to me that in the case of datasets there may be another solution,
depending on the nature of the variables you want to persist. If they are
simple, you could create a table in the dataset and stick the values in
there. Ugly, but not much worse.

There is another solution I can use because this is an asp.net app and I
control which instances are serialized (i.e., exactly the ones that are added
to the Session data store). In my case, the dataset is a member variable in a
class instance that is being serialized. When the containing class is being
serialized, in its getObjectData() method it can call a method in my half of
the dataset, e.g., getObjectDataKludge() that serializes its member
variables. Ditto for deserialization. I'll try this one today. Of course, it
is not generalizable and it only works if I know that one of my member
variables requires this special processing.

Thanks again - that was a big help. The references were excellent.

Marc



Jialiang Ge said:
Hello Marc,

From your post, my understanding on this issue is: you wonder how to extend
a partial class generated with DataSet designer and serialize the
properties in the extension. If I'm off base, please feel free to let me
know.

First, I hope to let you know that our managed newsgroup is focused on
break fix issues that are neither urgent, nor complex. If the issue is
urgent to your business, it is recommended that you contact Microsoft
Customer Support Services (CSS) via telephone so that a dedicated Support
Professional can assist you in a more efficient manner. Please be advised
that contacting phone support will be a charged call. To obtain the phone
numbers for specific technology request please take a look at the web site
listed at:
http://support.microsoft.com/default.aspx?scid=fh;EN-US;PHONENUMBERS. If
you are outside the US please see http://support.microsoft.com for regional
support phone numbers.

According to your description, the class Checklists inherits from
global::System.Data.DataSet and is signed with Serializable attribute. As
the MSDN article "Object Serialization in .NET"
(http://msdn2.microsoft.com/en-us/library/ms973893.aspx) says:
Case1: If a class is signed with "[Serializable()]" attribute and does not
implement ISerializable interface, the Common Language Runtime (CLR)
manages how objects are laid out in memory and the .NET Framework provides
an automated serialization mechanism by using reflection.
Case 2: If a class is signed with "[Serializable()]" attribute and
implements ISerializable interface, it will use the GetObjectData method
and a special constructor to serialize or deserialize the object.

Because System.Data.DataSet implements ISerializable interface, our
situation should fit the case 2. That is to say, .NET framework will use
the GetObjectData method and the deserialization contructor to
serialize/deserialize the object.

In your post, you extend the Checklists class by adding another partial
class. Because the properties var1, var2 in the extension are not added
into GetObjectData and the special constructor which is generated by the
designer, they will be lost when we try to serialize or deserialize them.

Here are several approaches to workaround it:
#1. As you said, we can make a derived class in which we override the
GetObjectData() and the desrialization contructor.

#2. We can add a wrapper class for Checklists.
That is to say, we could create a class and add Checklists object, var1,
var2 as its properties. Then we claim the class as Serializable and
implements ISerializable interface. Var1, var2 and the Checklists object
are serialized/deserialized respectively in GetObjectData and the special
constructor. For instance:
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("var1", var1);
info.AddValue("var2", var2);
info.AddValue("Checklists", checklists, typeof(checklists));
}

For more information about .net Serialization, you may refer to Jeffrey
Richter's three articles in MSDN Magazine:
http://msdn.microsoft.com/msdnmag/issues/02/04/net/
http://msdn.microsoft.com/msdnmag/issues/02/07/net/default.aspx
http://msdn.microsoft.com/msdnmag/issues/02/09/net/

Please let me know if you have any other concerns, or need anything else.

Sincerely,
Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
For MSDN subscribers whose posts are left unanswered, please check this
document: http://blogs.msdn.com/msdnts/pages/postingAlias.aspx

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications. If you are using Outlook Express/Windows Mail, please make sure
you clear the check box "Tools/Options/Read: Get 300 headers at a time" to
see your reply promptly.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Jailiang,

Here is my full solution. I ran into some additional serialization problems
relating to the fact that XPathDocument is nonserializable...

[Serializable()]
public class ChecklistChangedException : Exception
{
...
//MachineChecklist is a dataset with two partial class files, the
designer's and mine.
private MachineChecklist token;
...
public override void GetObjectData(SerializationInfo info,
StreamingContext context)
{
base.GetObjectData(info, context);
....
info.AddValue("token", token, typeof(MachineChecklist));
token.getObjectDataKludge(info, context);
...
}
protected ChecklistChangedException(SerializationInfo info,
StreamingContext context):base(info, context)
{
...
token = (MachineChecklist)(info.GetValue("token",
typeof(MachineChecklist)));
token.deserializationKludge(info, context);
...
}
}

public partial class MachineChecklist
{
...
List<ChecklistDoc> clDocs = new List<ChecklistDoc>(); //ChecklistDoc
contains a non-serializable XPathDocument
...
// The following two methods are a kludge required by the fact that
the ISerializable interface is implemented in
// the dataset's designer class and it will not de/serialize the
above instance variables. These methods
// MUST be called by any serializable class that contains this
dataset as an instance variable.
public void getObjectDataKludge(SerializationInfo info,
StreamingContext context)
{
...
info.AddValue("MachineChecklist.clDocs", clDocs,
typeof(List<ChecklistDoc>));
...
}
public void deserializationKludge(SerializationInfo info,
StreamingContext context)
{
...
clDocs =
(List<ChecklistDoc>)(info.GetValue("MachineChecklist.clDocs",
typeof(List<ChecklistDoc>)));
...
}
}

[Serializable]
public class ChecklistDoc
{
[NonSerialized] //XPathDocument is not serializable
private XPathDocument theChecklist;
private string mappedPath;
[OnDeserialized] //Recreate the XPathDocument
internal void onDeserializedMethod(StreamingContext context)
{
if (mappedPath != null)
{
theChecklist = new XPathDocument(mappedPath);
}
}
...
}
 
J

Jialiang Ge [MSFT]

Hello Marc,

I did a test with your code, and it worked well on my side. XPathDocument
is a class not implementing ISerializable interface. I notice that you
added the code:

[NonSerialized]
private XPathDocument theChecklist;

[OnDeserialized]
public void onDeserializedMethod(StreamingContext context)
{
if (mappedPath != null)
{
theChecklist = new XPathDocument(mappedPath);
}
}

The code above ensures that .NET framework will not try to serialize the
XPathDocument object and the object will be recreated in deserialization
according to the mapped path property.

As the article http://msdn.microsoft.com/msdnmag/issues/02/04/net/ says, in
general, there are two reasons why you would not want some of a type's
instance fields to be serialized. The first reason is that the field
contains information that would not be valid when deserialized. For
example, an object that contains a handle to a Windows kernel object (such
as a file, process, thread, mutex, event, semaphore, and so on) would have
no meaning when deserialized into another process or machine since Windows
kernel handles are process-relative values. Another reason is that the
field contains information that is easily calculated. In this case, you
select which fields do not need to be serialized, thus improving your
application's performance by reducing the amount of data transferred. Here,
the non-serialization of XPathDocument class should fit the first reason:
the field contains information that would not be valid when deserialized.

If I misunderstood your 'additional serialization problem', please point it
out.

Regards,
Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

=================================================
When responding to posts, please "Reply to Group" via your newsreader
so that others may learn and benefit from your issue.
=================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Jialiang

Yes, I think we both understand and agree about what's going on here. I read
the article you referenced but still found it curious that XpathDocument (and
XmlDocument) are not marked as Serializable. I can't think of what could be
in an XPathDocument that meets the first criterion.

Thx
Marc
 
J

Jialiang Ge [MSFT]

Hello Marc,

From my point of view, XPathDocument is not declared as Serializable
because of the following possible reasons:

1. Inside XPathDocument (If you use .NET Reflector to view the realization
of XPathDocument), it uses an array of XPathNode to read the nodes of the
xml document. XPathNode is not serializable, and actually, almost all the
classes in System.XML namespace are not designed as serializable.
2. It is very easy to rebuild the XPathDocument object according to the
input stream or file, so it is not necessary to serialize the XPathDocument
object, especially when the input is a very large stream. This fits the
criterion 2.
3. XPathDocument may sometimes work with xml documents in the file system.
This fit the criterion 1.

The reasons above may not be complete, because they are my personal opions.
If you have any other concern or need anything else, please feel free to
let me know.

Regards,
Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

=================================================
When responding to posts, please "Reply to Group" via your newsreader
so that others may learn and benefit from your issue.
=================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

Jialiang Ge [MSFT]

Hi Marc,

If you need further assistance, feel free to let me know. I will be more
than happy to be of assistance.

Have a great day!

Sincerely,
Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

=================================================
When responding to posts, please "Reply to Group" via your newsreader
so that others may learn and benefit from your issue.
=================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top