简体   繁体   English

为什么我们需要为类和属性装饰序列化属性或实现一些用于持久化数据的接口?

[英]Why do we need to decorate serialisation attributes to classes and properties or implement some interface for persisting the data?

As far as my understanding goes most of the serialization/de-serialization technique uses reflection to create object and set or get values.就我的理解而言,大多数序列化/反序列化技术使用反射来创建对象并设置或获取值。 So why do one explicitly bind these attribute such as [XmlIgnore]... for xml, [Serializable]... in Binary serialisation, [JsonPropery]... Json.Net etc in the class.那么为什么要明确绑定这些属性,例如 [XmlIgnore]... 用于 xml,[Serializable]... 在二进制序列化中,[JsonPropery]... Json.Net 等在类中。 Since these are like cross cutting concerns as a far as an object concerned, cant we do the same outside the object?既然就对象而言,这些就像横切关注点一样,我们不能在对象之外做同样的事情吗?

If the concerns are separated the user can have control over which portion of the object graph/tree one needs to serialize/de- serialize under which context and how etc?如果关注点被分离,用户可以控制对象图/树的哪个部分需要在哪个上下文以及如何序列化/反序列化等?

Is there any such framework that makes the entire serialization as aspect, ie outside the concern of the classes?是否有任何这样的框架使整个序列化作为方面,即在类的关注之外?

Edit1: My requirements are as follows My application stores the data in a huge tree structure. Edit1:我的要求如下我的应用程序将数据存储在一个巨大的树结构中。 The customer requirement is to be able to serialize certain data in xml format, and certain portion of the data in Json (I do not know why such requirement) and we have most of the data serialized in binary as a legacy code.客户的要求是能够序列化xml格式的某些数据,和Json的某些部分数据(我不知道为什么会有这样的要求),我们将大部分数据序列化为二进制作为遗留代码。

Now that there are classes in which a portion of the data needs to be shown in XML format and another portion (these can be part of the xml data or binary serialization data as well) in Json.现在有一些类,其中一部分数据需要以 XML 格式显示,另一部分(这些也可以是 xml 数据或二进制序列化数据的一部分)在 Json 中。

So I am looking for a solution in which所以我正在寻找一个解决方案

  1. Classes should not be aware of any serialization specific attributes, instead the serializer framework can give enough tools to easily do serialization without touching the class.类不应该知道任何特定于序列化的属性,相反,序列化器框架可以提供足够的工具来轻松地进行序列化而无需触及类。
  2. The framework should allow persisting both private and public data which I wanted.该框架应该允许保留我想要的私有和公共数据。 This can be specific to a class or instance or specific to some properties of an instance in some context.这可以特定于类或实例,或者特定于某些上下文中实例的某些属性。
    Eg例如
    • SaveTemplate: Should save only few nodes from each branch of the tree SaveTemplate:应该只保存树的每个分支中的几个节点
    • SaveDocument: Should save one branch from the tree completely SaveDocument:应该完全从树中保存一个分支
    • SavePackage: Should save entire tree. SavePackage:应该保存整个树。
  3. Should allow serialize into different format, such as xml, binary, json etc for different purposes.应该允许序列化为不同的格式,例如 xml、binary、json 等用于不同的目的。

So I am planning to evaluate certain Serialization framework to achieve the same.所以我计划评估某些序列化框架以实现相同的目标。 I found Json.Net which can give me the following我找到了 Json.Net,它可以给我以下内容

  • No serialization tag to be put for public properties just like xml serialization .没有像xml 序列化那样为公共属性放置序列化标记。
  • Backward compatibility to Binary Serialization.向后兼容二进制序列化。 ie I do not have to change the binary serialization interface implementation即我不必更改二进制序列化接口实现
  • Does not need a parameter less constructor.不需要无参数构造函数。

However I still need the capability mentioned in point 2) and 3) above.但是,我仍然需要上面第 2) 和 3) 点中提到的功能。 I have not yet explored Json.Net in detail or any other framework.我还没有详细探索 Json.Net 或任何其他框架。

Does any framework can help me achieve the same?是否有任何框架可以帮助我实现相同的目标?

Well, yes.嗯,是。 XML serialization can work on any object with the following two caveats, neither of which require attribute decoration: XML 序列化可以在任何对象上工作,但有以下两个注意事项,它们都不需要属性修饰:

  • The object must have a public, parameterless constructor.该对象必须有一个公共的、无参数的构造函数。
  • All information that should be serialized must be in a publicly-visible field or property.所有应序列化的信息必须位于公开可见的字段或属性中。

Easy.简单。 However, XML serialization without attributes produces the "default" XML structure for the object.但是,不带属性的 XML 序列化会为对象生成“默认”XML 结构。 If you're trying to make the XML class produced by serializing your object conform to a pre-existing XML document format, like a SOAP request, or HTML or XAML, this default structure probably won't work, and so it must be customized by using either attributes, telling the built-in serializer engine how to tweak what it produces, or a custom serialization routine that basically overrides the built-in engine and does exactly what you want.如果您试图使通过序列化对象生成的 XML 类符合预先存在的 XML 文档格式,如 SOAP 请求、HTML 或 XAML,则此默认结构可能不起作用,因此必须对其进行自定义通过使用任一属性,告诉内置序列化引擎如何调整它产生的内容,或者使用自定义序列化例程,基本上覆盖内置引擎并完全按照您的要求执行。

Binary serialization, at its most basic, requires one single attribute, Serializable, to be applied to the class itself.二进制序列化最基本的要求是将一个属性 Serializable 应用于类本身。 This is little more than a hint to the compiler or runtime that this class's definition should be included in a set of "serialization assemblies" that are created for that purpose.这只不过是对编译器或运行时的一个提示,即此类的定义应包含在为此目的创建的一组“序列化程序集”中。 However, again, if you just tell it the object can be serialized, and don't tell it how , you get the default behavior;然而,再一次,如果你只是告诉它对象可以被序列化,而不告诉它如何,你会得到默认行为; fields may be included that you don't want, or the serializer may run into trouble with something it can't serialize.可能包含您不想要的字段,或者序列化程序可能会遇到无法序列化的问题。

In short, there are several built-in or freely-available serializers that will work with a bare minimum of metadata;简而言之,有几个内置的或免费可用的序列化程序,可以使用最少的元数据; however, their usefulness would be sharply limited if they didn't allow you to customize the process to produce exactly the results you need.但是,如果它们不允许您自定义流程以准确产生您需要的结果,那么它们的实用性将受到极大限制。 So, they do.所以,他们这样做。

With your edit, referring to private fields among other things: frankly you're stretching the feature-set of what any one serializer will offer.通过您的编辑,除其他事项外,还涉及私有字段:坦率地说,您正在扩展任何一个序列化程序将提供的功能集。 You can probably use extension APIs to do some of it, but it'll be a lot of work, and not 100%.您可能可以使用扩展 API 来完成其中的一些工作,但这需要大量工作,而不是 100%。 You will spend a lot if time fighting the serializers and debugging.如果时间与序列化程序和调试进行斗争,您将花费很多。

In such cases, there is a much better solution: write a set of DTO types completely unrelated to your domain entities.在这种情况下,有一个更好的解决方案:编写一组与域实体完全无关的 DTO 类型。 Serialize/deserialize the DTOs - feel free go annotate the DTOs like there is no tomorrow: their single purpose is to express serialization intent.序列化/反序列化 DTO - 随意注释 DTO,就像没有明天一样:它们的唯一目的是表达序列化意图。 Then just map to/from the DTO and entity types.然后只需映射到/从 DTO 和实体类型。

This way, you get the best if both worlds.通过这种方式,您可以获得最好的两个世界。 The serializers are happy with the DTOs (and you can shape the data as you want, by tweaking the DTO types), and your domain entities are squeaky clean, completely unaware of serialization concerns.序列化器对 DTO 很满意(您可以通过调整 DTO 类型来根据需要调整数据),并且您的域实体非常干净,完全不知道序列化问题。

Usually your class/instance will have a lot of private fields and other public properties that are irrelavant for the XML.通常,您的类/实例将具有许多与 XML 无关的私有字段和其他公共属性。

Attributes like [XMLElement(...)] are also used to define a name of the XML element that never changes. [XMLElement(...)] 之类的属性也用于定义永不更改的 XML 元素的名称。 Even if you change the name of the property in your class, serializing and desrializing will still work.即使您更改了类中的属性名称,序列化和反序列化仍然有效。

If you do not want to use these elements, you are free to implement your own XMLWriter or XMLReader.如果您不想使用这些元素,您可以自由实现自己的 XMLWriter 或 XMLReader。 You can also create an instance of XMLWriter and use it's Write methods to write whatever your want.您还可以创建 XMLWriter 的实例并使用它的 Write 方法来编写您想要的任何内容。

Yes.是的。 You can do this with XmlSerializer if you don't mind configuring a XmlAttributeOverrides instance at runtime and passing that into the overloaded constructor.如果您不介意在运行时配置XmlAttributeOverrides实例并将其传递给重载的构造函数,则可以使用XmlSerializer执行此操作。 With this approach you can do everything you can do with XML attributes, but it is critical that you cache and re-use the serializer you create when doing this (don't create a new instance each time).使用这种方法,您可以使用 XML 属性执行您可以执行的所有操作,但在执行此操作时缓存和重用您创建的序列化程序至关重要(不要每次都创建一个新实例)。

For binary, protobuf-net allows you to configure it at runtime via RuntimeTypeModel , for example RuntimeTypeModel.Default.Add(typeof(SomeClass), false).Add("X", "Y", "Z");对于二进制,protobuf-net 允许您在运行时通过RuntimeTypeModel对其进行配置,例如RuntimeTypeModel.Default.Add(typeof(SomeClass), false).Add("X", "Y", "Z"); . . The reality, though, is that serializers are often complex with lots of options.然而,现实是序列化程序通常很复杂,有很多选项。 In most cases, it is simply easier to keep the configuration with the entities.在大多数情况下,保持实体的配置更容易。 But yes: some do allow you to fully configure them at runtime.但是是的:有些确实允许您在运行时完全配置它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 实现接口的具体类是否需要完全遵循接口定义? (没有额外的属性和方法) - Do the concrete classes that implement an interface need to follow the interface definition exactly? (with no extra properties and methods) 如果我们使用的所有类通常都继承自某个公共类,那么为什么需要泛型? - Why do we need generics if all classes we used usually inherit from some common class? 为什么我们需要密封类? - Why do we need sealed classes? 我们真的需要在Repository或UnitOfWork类中实现IDisposable吗? - Do we really need to implement IDisposable in Repository or UnitOfWork classes? 我们为什么要实现接口? - Why we should implement Interface? 如何在带有.NET桥的Progress Openedge ABL中使用属性装饰类,方法和属性? - How to decorate classes, methods and properties with attributes in Progress Openedge ABL with .NET bridge? 为什么我们需要将Object类作为所有类的基类? - Why do we need to have Object class as baseclass for all the classes? 需要帮助理解实现接口的抽象类 - Need help understanding abstract classes that implement an interface 为什么Code First类需要导航属性? - Why do Code First classes need navigation properties? 我只需要实现接口的一些方法 - I need Implement interface some methods only
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM