0

i just started to play a little bit with Binary Serialization.

I have a class "SerializeMe" which i want to serialize:

[Serializable]
public class ViewModelBase : INotifyPropertyChanged
{
    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void RaisePropertyChanged(
                      [CallerMemberName]string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

[Serializable]
public class SerializeBase : ViewModelBase
{
  .
  .
  .
}

Class i want to serialize:

[Serializable]
public class SerializeMe : SerializeBase 
{
     .
     .
     .
}

In my MainViewModel i have an ObservableCollection of type "SerializeBase" and a Method which serializes the first item in the collection:

public class MainViewModel : ViewModelBase
{
   private ObservableCollection<SerializeBase> _workspaces;

   public MainViewModel()
   {
      _workspaces = new ObservableCollection<SerializeBase>
   // EDIT
                    {
                         new SerializeMe(),
                         new SerializeMe()
                    }
   // EDIT END
   }

   public ObservableCollection<SerializeBase> Workspaces
   {
         get { return _workspaces; }
         set
         {
               if (value == _workspaces)
                   return;

               _workspaces = value;
               RaisePropertyChanged();
         }
   }

   public void SerializeFirst()
   {
        var fisrtItem = _workspaces.FirstOrDefault();
        if (firstItem == null)
            return;

        using(var stream = new FileStream("file.bin", FileMode.Create))
        {
            new BinaryFormatter().Serialize(stream, firstItem);
        }
   }
}

All this works just if i mark my MainViewModel as Serializable.

This works:

namespace Namespace
{
   [Serializable]
   public class MainViewModel : ViewModelBase
   .
   .
   .

This not:

namespace Namespace
{
   public class MainViewModel : ViewModelBase
   .
   .
   .

Error detail: The type MainViewModel... is not marked as Serializable.

Could someone explain why my MainViewModel has to be serializable? I don't get it.

Thanks.

  • Just because parent classes are serializable doesn't mean that the child classes are. You have to explicitly tell it that it can be serialized otherwise it assumes it can't. At least thats how the `[Serializable]` attribute works. If you had implemented `ISerializable` on the base class, then I think it works. – Ron Beyer Jul 09 '15 at 13:43
  • Thank you for the answer, but: I DON'T want to serialize my MainViewModel. Only the first item in _workspaces Collection – Denis Aleshin Jul 09 '15 at 13:45
  • You may want to clarify your question then because its not apparent that `Workspaces` would not contain the `MainViewModel` reference, since it derives from a common base class it seems that it certainly could. – Ron Beyer Jul 09 '15 at 13:48
  • completely off topic -- why you want to serialize a view model ? – Muds Jul 09 '15 at 13:54
  • Don't sure if i understand your comment right. Workspaces CAN'T hold a refenrece of MainViewModel, MainViewModel is derived from ViewModelBase and not SerializeBase – Denis Aleshin Jul 09 '15 at 13:54
  • Again: I DON'T want to serialize my MainViewModel, BUT if i try to serialize the first item in Workspaces i get a error which says that my MainViewModel is not marked as serializable -- if i mark my MainViewModel serializable -- it works. My question is: Why my MainViewModel has to be serializable? – Denis Aleshin Jul 09 '15 at 13:58
  • Why binary serialization? Avoid it at all cost. There are many choices: `XmlSerializer`/`DataContractSerializer`, json, protobuf, ... And you choose **the worst**. There are many reasons why: [click](http://stackoverflow.com/a/4743878/1997232), [click](http://stackoverflow.com/q/5091712/1997232), ... All kind of troubles awaits you (change the type of field and you are screwed, etc.). – Sinatr Jul 09 '15 at 14:15
  • It's because what you want to serialize has a reference to the MainViewModel. How, I don't know. But I *do* know it isn't magic--if you serialize an instance of X, and it fails because type Y isn't serializable, ***then that instance of X holds a reference to an instance of type Y***. That's 100% sure. I'd suggest that you debug, and **right before** serializing you check that object graph from top to bottom. **This includes events, as subscribers to an event will also get serialized!** Hmmm... come to think of it... –  Jul 09 '15 at 14:17
  • I bet your VM is in the visual tree, and the visual tree is subscribed to INPC events, and your main view model is *also* in the visual tree, and the whole goddamn thing is being serialized. Quick solution--don't use binary serialization. Almost every other type of serializer won't serialize event listeners. –  Jul 09 '15 at 14:19
  • @Will THANK YOU! MainViewModel subscribes to an event in SerializeMe. – Denis Aleshin Jul 09 '15 at 14:23
  • @Sinatr Thank you, gonna check the links. – Denis Aleshin Jul 09 '15 at 14:23
  • Aha, that might be it. Better than the entire visual tree coming with. Although, that's still possible. You should debug, serialize SerializeMe before you attach it to anything, then afterwards. Compare the two results. If one is much larger than the other, you're serializing tons of stuff unintentionally. –  Jul 09 '15 at 14:27
  • What's the purpose of putting the comment in the question? Have you fixed the issue? If so, I can slap it in an answer below. –  Jul 09 '15 at 14:29
  • @Will Yes, i fixed it. MainViewModel subscribes to an event in SerializeMe, the event was not marked as [field: NonSerialized] – Denis Aleshin Jul 09 '15 at 14:32
  • Okay, but answers go below in StackOverflow. I'll add one and you can close this out. –  Jul 09 '15 at 14:34

2 Answers2

1

I've had this exact problem recently while trying to serialize a large data set.

The problem is that somehow or other one of your models has ended up with a link to some element from the view model\commands\converters you are using, and as such the serializer thinks it needs to serialize the entire view model.

If you do mark the main view model as Serializable it will start going through all other view models and commands connected to your main view model and give you the same problem with those.

You need to find out what is getting connected and where and then stop it from happening.

sidjames
  • 117
  • 6
0

It's because what you want to serialize has a reference to the MainViewModel. How, I don't know. But I do know it isn't magic.

if you serialize an instance of X, and it fails because type Y isn't serializable, then that instance of X holds a reference to an instance of type Y. That's 100% sure.

Normally, you should debug, and right before serializing you check that object graph from top to bottom. For binary serialization, this includes events, as binary serialization will serialize event listeners as well.

Binary serialization is so 1.0. You should look into more recent developments in serialization technologies. The NetDataContractSerializer and xaml serialization are good fits for most of your .NET needs. Json is fine for when your Types aren't that important. None of these will serialize event listeners.