开发者

Can I serialize an object if I didn't write the class used to instantiate that object?

I've a simple class

[Serializable]
public class MyClass
{
  public String FirstName { get; set: }
  public String LastName { get; set: }

  //Bellow is what I would like to do
  //But开发者_开发百科, it's not working
  //I get an exception
  ContactDataContext db = new ContactDataContext();

  public void Save()
  {
   Contact contact = new Contact();
   contact.FirstName = FirstName;
   contact.LastName = LastName;

   db.Contacts.InsertOnSubmit(contact);
   db.SubmitChanges();
  }
}

I wanted to attach a Save method to the class so that I could call it on each object. When I introduced the above statement which contains ContactDataContext, I got the following error "In assembly ... PublicKeyToken=null' is not marked as serializable"

It's clear that the DataContext class is generated by the framework (). I checked and did not see where that class was marked serialize.

What can I do to overcome that? What's the rule when I'm not the author of a class? Just go ahead and mark the DataContext class as serializable, and pretend that everything will work?

Thanks for helping


It might be worth taking a step back and seeing if what you want to achieve is really valid.

Generally, a serializable class is used for data transport between two layers. It is more likely to be a simple class that only holds data.

It seems a little out of place for it to hold the ability to persist to a database. It is not likely that both ends of the pipe actually have access to the database, and it seems very unlikely that they would both have the ability to persist data.

I wonder if it's worth factoring the save out to a repository. So have a repository class that will accept the data transfer object, construct the database object and save it.

This will simplify your code and completely avoid the problem you're having. It will also greatly enhance testability.


The problem is that the db field gets serialized, while clearly it doesn't need to be serialized (it's instantiated once the object is created).

Therefore, you should decorate it with the NonSerialized attribute:

[NonSerialized] 
ContactDataContext db = new ContactDataContext();

[Update]

To make sure the db field is accesable after object initialization, you should use a lazy loading property and use this property instead of the field:

[NonSerialized] 
ContactDataContext db = null;

[NonSerialized] 
private ContactDataContext {
    get {
        if (db == null) {
            db = new ContactDataContext();
        }
        return db;
    }
    set {
        db = value;
    }
}

public void Save()
{
    Contact contact = new Contact();
    contact.FirstName = FirstName;
    contact.LastName = LastName;

    Db.Contacts.InsertOnSubmit(contact);
    Db.SubmitChanges();
}

[Update2]

You can serialize most objects, as long as it has a public parameterless constructor (or no constructor at all) and no properties/fields that cannot be serialized but require serializing. If the class itself is not marked as [Serializable], then you can do this yourself using a partial class. If the class has properties/fields that cannot be serialized, then you might achieve this by inheriting the class and overriding these properties/fields to decorate them as [NonSerialized].


You can create a surrogate that knows how to serialize the dodgy classes - see here for an example


I think you do need to decorate the base class, however, the DataContext auto generated classes are marked as partial. Have you tried doing something like:

[Serializable]
public partial class ContactDataContext
{
}

Not sure if it would work but its worth a try.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜