Могу ли я сериализовать объект, если я не написал класс, используемый для создания экземпляра этого объекта? - PullRequest
2 голосов
/ 15 апреля 2010

У меня простой класс

[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();
  }
}

Я хотел прикрепить метод Save к классу, чтобы я мог вызывать его для каждого объекта. Когда я ввел вышеупомянутое утверждение, которое содержит ContactDataContext , я получил следующую ошибку " В сборке ... PublicKeyToken = null" не помечен как сериализуемый"

Понятно, что класс DataContext генерируется framework (). Я проверил и не увидел, где этот класс был отмечен serialize .

Что я могу сделать, чтобы преодолеть это? Каково правило, когда я не являюсь автором класса? Просто отметьте класс DataContext как сериализуемый и сделайте вид, что все будет работать?

Спасибо за помощь

Ответы [ 4 ]

2 голосов
/ 19 апреля 2010

Возможно, стоит сделать шаг назад и посмотреть, действительно ли то, чего вы хотите достичь, действительно.

Как правило, сериализуемый класс используется для передачи данных между двумя уровнями. Скорее всего, это будет простой класс, который содержит только данные.

Кажется, это немного неуместно для сохранения способности сохраняться в базе данных. Маловероятно, что оба конца канала на самом деле имеют доступ к базе данных, и очень маловероятно, что они оба смогут сохранять данные.

Интересно, стоит ли учитывать сохранение в хранилище? Поэтому есть класс репозитория, который будет принимать объект передачи данных, создавать объект базы данных и сохранять его.

Это упростит ваш код и полностью избавит вас от проблемы. Это также значительно улучшит тестируемость.

1 голос
/ 15 апреля 2010

Проблема в том, что поле db сериализуется, хотя, очевидно, его не нужно сериализовать (оно создается после создания объекта).

Поэтому вы должны украсить его атрибутом NonSerialized:

[NonSerialized] 
ContactDataContext db = new ContactDataContext();

[Update]

Чтобы убедиться, что поле db доступно после инициализации объекта, вы должны использовать свойство отложенной загрузки и использовать это свойство вместо поля:

[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]

Вы можете сериализовать большинство объектов, если у них есть открытый конструктор без параметров (или вообще без конструктора) и нет свойств / полей, которые не могут быть сериализованы, но требуют сериализации. Если сам класс не помечен как [Serializable], то вы можете сделать это самостоятельно, используя частичный класс. Если у класса есть свойства / поля, которые нельзя сериализовать, то этого можно достичь, унаследовав класс и переопределив эти свойства / поля, чтобы украсить их как [NonSerialized].

1 голос
/ 17 апреля 2010

Вы можете создать суррогат, который знает, как сериализовать хитрые классы - см. здесь для примера

0 голосов
/ 15 апреля 2010

Я думаю, вам нужно украсить базовый класс, однако автоматически сгенерированные классы DataContext помечены как partial. Вы пытались сделать что-то вроде:

[Serializable]
public partial class ContactDataContext
{
}

Не уверен, что это сработает, но стоит попробовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...