.NET, C#: How to add a custom serialization attribute that acts as ISerializable interface

后端 未结 2 1529
旧时难觅i
旧时难觅i 2021-01-03 04:39

I am doing some serialization of db linq objects, which contain EntitySet and EntityRef classes.

I found a pretty easy way to deal with serialization of these classe

相关标签:
2条回答
  • 2021-01-03 04:53

    Yes, you can do this by implementing ISerializationSurrogate and ISurrogateSelector interfaces.

    Something like this:

    [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);
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-03 05:09

    Unfortunately no, ISerializable is an interface designed to allow you to control the serialization process while the SerializableAttribute is just a marker that says "this class can be serialized". However, you could look into something like PostSharp to add this functionality (take a look at the CompositionAspect).

    0 讨论(0)
提交回复
热议问题