Serialization和Marshaling有什么区别?

点点圈 提交于 2020-02-26 05:29:45

我知道,就几种分布式技术(如RPC)而言,使用术语“编组”但不理解它与序列化的区别。 它们不是都将对象转换为一系列位吗?

有关:

什么是序列化?

什么是对象编组?


#1楼

两者都有一个共同点 - 即序列化对象。 序列化用于传输对象或存储它们。 但:

  • 序列化:序列化对象时,只将该对象中的成员数据写入字节流; 而不是实际实现对象的代码。
  • 编组:当我们讨论将Object传递给远程对象(RMI)时使用术语编组。 在编组对象中序列化(成员数据被序列化) +附加了代码库。

因此序列化是编组的一部分。

CodeBase是告诉Object的接收者可以找到该对象的实现的信息。 任何认为它可能将对象传递给之前可能没有看到它的另一个程序的程序必须设置代码库,以便接收方可以知道从哪里下载代码,如果它没有本地可用的代码。 在对对象进行反序列化时,接收器将从中获取代码库并从该位置加载代码。


#2楼

我对编组的理解与其他答案不同。

连载:

使用约定生成或重新水化对象图的线格式版本。

编组:

使用映射文件生成或重新生成对象图的线型版本,以便可以自定义结果。 该工具可以从遵守惯例开始,但重要的区别在于自定义结果的能力。

合同优先发展:

在合同首次开发的背景下,编组很重要。

  • 它可以对内部对象图进行更改,同时保持外部接口随时间稳定。 这样,不必为每个微不足道的变化修改所有服务订户。
  • 可以跨不同语言映射结果。 例如,从一种语言('property_name')的属性名称约定到另一种语言('propertyName')。

#3楼

编组是告诉编译器如何在另一个环境/系统上表示数据的规则; 例如;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;

因为您可以看到两个不同的字符串值表示为不同的值类型。

序列化只会转换对象内容,而不是表示(将保持相同)并遵守序列化规则,(导出或不导出)。 例如,私有值不会被序列化,公共值为yes,对象结构将保持不变。


#4楼

以下是两个更具体的例子:

序列化示例:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef struct {
    char value[11];
} SerializedInt32;

SerializedInt32 SerializeInt32(int32_t x) 
{
    SerializedInt32 result;

    itoa(x, result.value, 10);

    return result;
}

int32_t DeserializeInt32(SerializedInt32 x) 
{
    int32_t result;

    result = atoi(x.value);

    return result;
}

int main(int argc, char **argv)
{    
    int x;   
    SerializedInt32 data;
    int32_t result;

    x = -268435455;

    data = SerializeInt32(x);
    result = DeserializeInt32(data);

    printf("x = %s.\n", data.value);

    return result;
}

在序列化中,数据以可以在以后存储和不平坦的方式展平。

编组演示:

(MarshalDemoLib.cpp)

#include <iostream>
#include <string>

extern "C"
__declspec(dllexport)
void *StdCoutStdString(void *s)
{
    std::string *str = (std::string *)s;
    std::cout << *str;
}

extern "C"
__declspec(dllexport)
void *MarshalCStringToStdString(char *s)
{
    std::string *str(new std::string(s));

    std::cout << "string was successfully constructed.\n";

    return str;
}

extern "C"
__declspec(dllexport)
void DestroyStdString(void *s)
{
    std::string *str((std::string *)s);
    delete str;

    std::cout << "string was successfully destroyed.\n";
}

(MarshalDemo.c)

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(int argc, char **argv)
{
    void *myStdString;

    LoadLibrary("MarshalDemoLib");

    myStdString = ((void *(*)(char *))GetProcAddress (
        GetModuleHandleA("MarshalDemoLib"),
        "MarshalCStringToStdString"
    ))("Hello, World!\n");

    ((void (*)(void *))GetProcAddress (
        GetModuleHandleA("MarshalDemoLib"),
        "StdCoutStdString"
    ))(myStdString);

    ((void (*)(void *))GetProcAddress (
        GetModuleHandleA("MarshalDemoLib"),
        "DestroyStdString"
    ))(myStdString);    
}

在编组中,数据不一定需要展平,但需要将其转换为另一种替代表示。 所有的铸造都是编组,但并非所有的编组都是铸造。

Marshaling不需要涉及动态分配,它也可以只是结构之间的转换。 例如,您可能有一对,但该函数期望该对的第一个和第二个元素是相反的; 你将一对转换成memcpy对另一对将无法完成这项工作,因为fst和snd会被翻转。

#include <stdio.h>

typedef struct {
    int fst;
    int snd;
} pair1;

typedef struct {
    int snd;
    int fst;
} pair2;

void pair2_dump(pair2 p)
{
    printf("%d %d\n", p.fst, p.snd);
}

pair2 marshal_pair1_to_pair2(pair1 p)
{
    pair2 result;
    result.fst = p.fst;
    result.snd = p.snd;
    return result;
}

pair1 given = {3, 7};

int main(int argc, char **argv)
{    
    pair2_dump(marshal_pair1_to_pair2(given));

    return 0;
}

当你开始处理许多类型的标记联合时,编组的概念变得尤为重要。 例如,您可能会发现很难让JavaScript引擎为您打印“c字符串”,但您可以要求它为您打印一个包装的c字符串。 或者,如果要在Lua或Python运行时中从JavaScript运行时打印字符串。 它们都是字符串,但如果没有编组,往往不会相处。

我最近遇到的烦恼是,JScript数组将C#编组为“__ComObject”,并且没有记录的方式来使用此对象。 我可以找到它所在的地址,但我真的不知道其他任何事情,所以真正弄明白的唯一方法是以任何可能的方式戳它并希望找到有关它的有用信息。 因此,使用更友好的界面(如Scripting.Dictionary)创建新对象变得更加容易,将JScript数组对象中的数据复制到其中,并将该对象传递给C#而不是JScript的默认数组。

test.js:

var x = new ActiveXObject("Dmitry.YetAnotherTestObject.YetAnotherTestObject");

x.send([1, 2, 3, 4]);

YetAnotherTestObject.cs

using System;
using System.Runtime.InteropServices;

namespace Dmitry.YetAnotherTestObject
{
    [Guid("C612BD9B-74E0-4176-AAB8-C53EB24C2B29"), ComVisible(true)]
    public class YetAnotherTestObject
    {
        public void send(object x)
        {
            System.Console.WriteLine(x.GetType().Name);
        }
    }
}

上面打印“__ComObject”,从C#的角度来看,它有点像黑盒子。

另一个有趣的概念是你可能已经理解了如何编写代码,以及知道如何执行指令的计算机,因此作为程序员,你有效地整理了你希望计算机从你的大脑到程序做什么的概念。图片。 如果我们有足够好的marshallers,我们可以想到我们想要做什么/改变什么,并且程序会改变这种方式而无需在键盘上打字。 所以,如果你有办法在你真正想要编写分号的几秒钟内存储大脑中的所有物理变化,你可以将这些数据编组成一个信号来打印分号,但这是极端的。


#5楼

Marshaling实际上使用了序列化过程,但主要区别在于它仅在序列化中仅数据成员和对象本身被序列化而不是签名,但在编组对象+代码库(其实现)中也将转换为字节。

编组是使用JAXB将java对象转换为xml对象的过程,以便可以在Web服务中使用它。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!