在一个程序集中序列化,在另一个程序集中反序列化



我在两个项目中有相同的类,一个在runtime上发送到另一个进程,该进程必须反序列化该对象并使用它(假设这两个对象相同,但程序集名称不同,因此它们实际上被解释为两种不同的类型)。根据我的研究,我提出了一些不起作用的解决方案,原因如下。

Json.NET:给我一个例外,这两种类型不兼容(尝试在序列化设置中使用typename.all)。

protobuf-net:要求我在每个位置添加属性,或者简单地为它提供属性名称(在v2中),由于我的对象太复杂,这两者对我来说都是不可能的。

BinaryFormatter:与protobuf->吨属性的原因相同。

Use Common Assembly:由于一些与我的项目架构有关的原因,我不能。

那么,有没有什么简单的方法可以序列化一个类型,然后将其反序列化为另一个类型(实际上是同一个类,但在不同的程序集中)?

是的,使用一个程序集中的类进行序列化,并使用Json.Net反序列化为另一个程序集的类是绝对可能的。事实上,这是序列化的主要用例之一——在不同系统之间传输数据。

你需要记住两件事:

  1. 如果源程序集和目标程序集不同,则应而不是在JSON中包含实际的完全限定类型名称作为元数据。换句话说,请确保TypeNameHandling设置设置为None(我认为这是默认设置)。如果包含类型名称元数据,那么Json.Net将期望在接收端找到这些程序集,并且反序列化将失败,因为不存在这些程序集
  2. 如果在类结构中使用接口而不是具体类型,则需要创建一个或多个JsonConverter类来处理反序列化。当Json.Net看到一个接口时,它将不知道要创建什么类型的具体类,因为它可以是任何东西。转换器可以查找JSON中可能存在的其他数据,并告诉JSON.Net要实例化哪个具体类。如果JSON中没有明显的数据段可以用作类型的指示符,则可以使用序列化端的转换器来添加自定义指示符

下面是一些示例代码来演示我所阐述的概念。演示分为两部分。第一部分是"sender",它将组成的"diagram"类结构序列化为JSON并将其写入文件。第二部分是"接收器",它读取文件并将JSON反序列化为一组不同的类。您会注意到,我有意使接收方中的一些类名与发送方不同,但它们具有相同的属性名和结构,因此它仍然有效。您还将注意到,接收器程序使用自定义JsonConverter来处理创建正确的IFigure实例,使用JSON中的某些属性作为指示符。

发件人

using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
namespace Sender
{
    class Program
    {
        static void Main(string[] args)
        {
            Diagram diagram = new Diagram
            {
                Title = "Flowchart",
                Shapes = new List<IShape>
                {
                    new Circle 
                    { 
                        Id = 1, 
                        Text = "Foo", 
                        Center = new Point { X = 1, Y = 5 }, 
                        Radius = 1.25 
                    },
                    new Line 
                    {
                        Id = 2,
                        A = new Point { X = 2.25, Y = 5 }, 
                        B = new Point { X = 4, Y = 5 } 
                    },
                    new Rectangle
                    {
                        Id = 3,
                        Text = "Bar",
                        TopLeft = new Point { X = 4, Y = 6.5 }, 
                        BottomRight = new Point { X = 8.5, Y = 3.5 } 
                    }
                }
            };
            string json = JsonConvert.SerializeObject(diagram, Formatting.Indented);
            File.WriteAllText(@"C:temptest.json", json);
        }
    }
    class Diagram
    {
        public string Title { get; set; }
        public List<IShape> Shapes { get; set; }
    }
    interface IShape
    {
        int Id { get; set; }
        string Text { get; set; }
    }
    abstract class AbstractShape : IShape
    {
        public int Id { get; set; }
        public string Text { get; set; }
    }
    class Line : AbstractShape
    {
        public Point A { get; set; }
        public Point B { get; set; }
    }
    class Rectangle : AbstractShape
    {
        public Point TopLeft { get; set; }
        public Point BottomRight { get; set; }
    }
    class Circle : AbstractShape
    {
        public Point Center { get; set; }
        public double Radius { get; set; }
    }
    class Point
    {
        public double X { get; set; }
        public double Y { get; set; }
    }
}

以下是Sender程序生成的JSON输出文件:

{
  "Title": "Flowchart",
  "Shapes": [
    {
      "Center": {
        "X": 1.0,
        "Y": 5.0
      },
      "Radius": 1.25,
      "Id": 1,
      "Text": "Foo"
    },
    {
      "A": {
        "X": 2.25,
        "Y": 5.0
      },
      "B": {
        "X": 4.0,
        "Y": 5.0
      },
      "Id": 2,
      "Text": null
    },
    {
      "TopLeft": {
        "X": 4.0,
        "Y": 6.5
      },
      "BottomRight": {
        "X": 8.5,
        "Y": 3.5
      },
      "Id": 3,
      "Text": "Bar"
    }
  ]
}

接收器

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Receiver
{
    class Program
    {
        static void Main(string[] args)
        {
            string json = File.ReadAllText(@"C:temptest.json");
            JsonSerializerSettings settings = new JsonSerializerSettings();
            settings.Converters.Add(new FigureConverter());
            Chart chart = JsonConvert.DeserializeObject<Chart>(json, settings);
            Console.WriteLine(chart);
            Console.ReadKey();
        }
    }
    class FigureConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return (objectType == typeof(IFigure));
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JObject jo = JObject.Load(reader);
            if (jo["Center"] != null)
            {
                return jo.ToObject<Circle>(serializer);
            }
            else if (jo["TopLeft"] != null)
            {
                return jo.ToObject<Rectangle>(serializer);
            }
            else
            {
                return jo.ToObject<Line>(serializer);
            }
        }
        public override bool CanWrite
        {
            get { return false; }
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
    class Chart
    {
        public string Title { get; set; }
        public List<IFigure> Shapes { get; set; }
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Chart: ");
            sb.AppendLine(Title);
            foreach (IFigure figure in Shapes)
            {
                sb.AppendLine(figure.ToString());
            }
            return sb.ToString();
        }
    }
    interface IFigure
    {
        int Id { get; set; }
        string Text { get; set; }
    }
    abstract class AbstractFigure : IFigure
    {
        public int Id { get; set; }
        public string Text { get; set; }
    }
    class Line : AbstractFigure
    {
        public Point A { get; set; }
        public Point B { get; set; }
        public override string ToString()
        {
            return string.Format("Line: A = {0}, B = {1}", A, B);
        }
    }
    class Rectangle : AbstractFigure
    {
        public Point TopLeft { get; set; }
        public Point BottomRight { get; set; }
        public override string ToString()
        {
            return string.Format("Rectangle: TopLeft = {0}, BottomRight = {1}", TopLeft, BottomRight);
        }
    }
    class Circle : AbstractFigure
    {
        public Point Center { get; set; }
        public double Radius { get; set; }
        public override string ToString()
        {
            return string.Format("Circle: Center = {0}, Radius = {1}", Center, Radius);
        }
    }
    class Point
    {
        public double X { get; set; }
        public double Y { get; set; }
        public override string ToString()
        {
            return string.Format("({0:0.##}, {1:0.##})", X, Y);
        }
    }
}

以下是接收器程序的输出:

Chart: Flowchart
Circle: Center = (1, 5), Radius = 1.25
Line: A = (2.25, 5), B = (4, 5)
Rectangle: TopLeft = (4, 6.5), BottomRight = (8.5, 3.5)

相关内容

  • 没有找到相关文章

最新更新