【问题标题】:.NET, C#: How to add a custom serialization attribute that acts as ISerializable interface.NET、C#:如何添加充当 ISerializable 接口的自定义序列化属性
【发布时间】:2010-02-01 04:01:44
【问题描述】:

我正在对包含 EntitySet 和 EntityRef 类的 db linq 对象进行一些序列化。

我找到了一种处理这些类序列化的非常简单的方法,只需使用 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);
  }
}

有没有办法做到这一点?我查看了序列化类,似乎找不到任何方法来设置自定义序列化过滤器例程(我可以在其中查找我的自定义属性)。

谢谢!

【问题讨论】:

  • 看起来 IClientFormatterSinkProvider 和 IServerFormatterSinkProvider 将允许我为我的自定义 SurrogateSelector 集提供 BinaryFormatter。再次感谢谢尔盖!
  • 嗯...所以,事实证明,微软让这件事变得比看起来要困难得多。请参阅以下链接:123aspx.com/Rotor/RotorSrc.aspx?rot=40027 Sink 提供程序,事实证明,是相当复杂的,它并不像实现一个那么简单。我真的希望他们提供更好的接口 API 来与二进制序列化接口......

标签: c# .net serialization custom-attributes


【解决方案1】:

是的,您可以通过实现 ISerializationSurrogateISurrogateSelector 接口来做到这一点。

类似这样的:

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

【讨论】:

  • 这正是我想要的(ISurrogateSelector 正是我想要的)。那么,最后一个问题 - 有没有办法将它与自动序列化一起使用?我的序列化是通过 RPC 调用发生的(使用 MarshalByRefObject)。
  • +1 我什至没有想到ISerializationSurrogate,因为问题明确提到了属性。此解决方案的唯一问题是您无权访问格式化程序实例来设置 SurrogateSelector 属性。
  • 在 WCF 中,您可以轻松地使用代理 (msdn.microsoft.com/en-us/library/ms733064.aspx)。我不使用 .net 远程处理的代理。也许自定义接收器可以帮助您 (codeproject.com/KB/IP/customsinks.aspx)。
【解决方案2】:

不幸的是,ISerializable 是一个旨在让您控制序列化过程的接口,而SerializableAttribute 只是一个标记,表示“此类可以序列化”。但是,您可以查看 PostSharp 之类的内容来添加此功能(查看 CompositionAspect)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多