.NET, C#: Как добавить пользовательский атрибут сериализации, который действует как интерфейс ISerializable

Я делаю некоторую сериализацию дб linq объекты, которые содержат классы EntitySet и EntityRef.

Я нашел довольно простой способ иметь дело с сериализацией этих классов путем простого использования ISerializable для надлежащей обработки членов этого типа (преобразовывающий их в списки для сериализации и отменяющий его на десериализации).

Однако было бы действительно хорошо, если я мог бы сделать:

[Serializable]
[SerializeLinqEntities]
partial class Person
{ ... }

Вместо:

partial class Person : ISerializable
{
  public virtual void GetObjectData( SerializationInfo si, StreamingContext ctxt )
  {
    EntitySerializer.Serialize(this, typeof(Person), si, ctxt);
  }

  protected Person( SerializationInfo si, StreamingContext ctxt )
  {
    EntitySerializer.Deerialize(this, typeof(Person), si, ctxt);
  }
}

Существует ли способ сделать это? Я просмотрел классы сериализации и, могло казаться, не нашел способа установить пользовательские стандартные программы фильтра сериализации (где я мог искать свой пользовательский атрибут).

Спасибо!

5
задан marq 1 February 2010 в 04:01
поделиться

2 ответа

Да, это можно сделать, реализовав интерфейсы ISerializationSurrogate и ISurrogateSelector.

Что-то вроде этого:

[AttributeUsage(AttributeTargets.Class)]
public class SerializeLinqEntities : Attribute
{
}

public class LinqEntitiesSurrogate : ISerializationSurrogate
{
    public void GetObjectData(
      object obj, SerializationInfo info, StreamingContext context)
    {
        EntitySerializer.Serialize(this, obj.GetType(), info, context);
    }

    public object SetObjectData(
      object obj, SerializationInfo info,
      StreamingContext context, ISurrogateSelector selector)
    {
        EntitySerializer.Deserialize(obj, obj.GetType(), info, context);
        return obj;
    }
}


/// <summary>
/// Returns LinqEntitySurrogate for all types marked SerializeLinqEntities
/// </summary>
public class NonSerializableSurrogateSelector : ISurrogateSelector
{
    public void ChainSelector(ISurrogateSelector selector)
    {
        throw new NotImplementedException();
    }

    public ISurrogateSelector GetNextSelector()
    {
        throw new NotImplementedException();
    }

    public ISerializationSurrogate GetSurrogate(
      Type type, StreamingContext context, out ISurrogateSelector selector)
    {
        if (!type.IsDefined(typeof(SerializeLinqEntities), false))
        {
            //type not marked SerializeLinqEntities
            selector = null;
            return null;
        }
        selector = this;
        return new LinqEntitiesSurrogate();
    }

}

[SerializeLinqEntities]
public class TestSurrogate
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class Program
{
    static void Main(string[] str)
    {

        var ns1 = new TestSurrogate {Id = 47, Name = "TestName"};
        var formatter = new BinaryFormatter();
        formatter.SurrogateSelector = new NonSerializableSurrogateSelector();

        using (var ms = new MemoryStream())
        {
            formatter.Serialize(ms, ns1);
            ms.Position = 0;

            var ns2 = (TestSurrogate) formatter.Deserialize(ms);
            // Check serialization
            Debug.Assert(ns1.Id == ns2.Id);
            Debug.Assert(ns1.Name == ns2.Name);
        }
    }
}
7
ответ дан 14 December 2019 в 08:50
поделиться

К сожалению нет, Iserializable - это интерфейс, предназначенный для того, чтобы позволить вам контролировать процесс сериализации, в то время как Serializableattribute Просто маркер, который говорит: «Этот класс может быть сериализован». Тем не менее, вы можете посмотреть на что-то вроде PostSharp , чтобы добавить эту функциональность (посмотрите на композицию ).

0
ответ дан 14 December 2019 в 08:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: