Skip to content

Enable serialization of POCO types via MobileFormatter #2148

Closed
@rockfordlhotka

Description

@rockfordlhotka

There are times when it would be nice to include a simple POCO style type in an object graph. Right now the most basic serializable type is MobileObject, which requires manual work to serialize things like fields.

There are several thoughts to consider. One is documented here, which is to use a base class. Another would be to have MF trigger on an attribute that delegates to an arbitrary "serializer" that returns/accepts a byte[] representing that class. Yet another would be to pass in a list of serializers to MobileFormatter (via DI), where each of these serializers would have the opportunity to say that they can serialize a given type that would otherwise not be serialized by MF.

MobilePoco base class

It is possible to create a MobilePoco type that uses reflection to get/set property and field values as needed by the MobileFormatter. This should be added to the Csla.Core namespace.

Here's a quick prototype of the idea:

using System;
using Csla.Serialization.Mobile;

namespace ConsoleApp3
{
  [Serializable]
  public abstract class MobilePoco : IMobileObject
  {
    void IMobileObject.GetChildren(SerializationInfo info, MobileFormatter formatter)
    {
    }

    void IMobileObject.SetChildren(SerializationInfo info, MobileFormatter formatter)
    {
    }

    private const System.Reflection.BindingFlags bindingFlags =
      System.Reflection.BindingFlags.Public |
      System.Reflection.BindingFlags.NonPublic |
      System.Reflection.BindingFlags.Instance;

    void IMobileObject.GetState(SerializationInfo info)
    {
      var fields = this.GetType().GetFields(bindingFlags);
      foreach (var item in fields)
        info.AddValue(item.Name, item.GetValue(this));
      var properties = this.GetType().GetProperties(bindingFlags);
      foreach (var item in properties)
        info.AddValue(item.Name, item.GetValue(this));
    }


    void IMobileObject.SetState(SerializationInfo info)
    {
      var fields = this.GetType().GetFields(bindingFlags);
      foreach (var item in fields)
        item.SetValue(this, info.GetValue<object>(item.Name));
      var properties = this.GetType().GetProperties(bindingFlags);
      foreach (var item in properties)
        item.SetValue(this, info.GetValue<object>(item.Name));
    }
  }
}

SerializeUsing attribute

[SerializeUsing(typeof(MySerializer))]
public class MyPoco {}

Presumably the MySerializer type would implement Csla.Serialization.ISerializationFormatter.

Custom Serializer List

Regarding the DI injection of a list of serializers, those serializers might implement an interface like this:

public interface ISerializer
{
    bool SerializesType(Type type);
    byte[] Serialize(object obj);
    object Deserialize(byte[] data);
}

When MF encounters a type it wouldn't otherwise be able to serialize, it would go through the list of custom serializers, calling SerializesType on each. If one returns true, then it would be used to serialize the object in question.

This technique could be used to generalize the way ClaimsPrincipal is currently handled. Right now it is hard-coded into MF as an exception, but that implementation could be moved out to a custom serializer instead.

Metadata

Metadata

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions