Protobuf-net扩展?我可以以不同的方式序列化特殊对象吗?

时间:2013-11-15 16:40:15

标签: protobuf-net

我是堆叠溢出的新手,如果已经提出这个问题,我道歉;我到处看,我找不到任何东西。最相关的主题是这个

Is there an extensibility mechanism in protobuf-net to control raw de/serialization?

问题是,我正在使用protobuf-net序列化方法,我想在序列化/反序列化过程中以不同的方式处理一些对象(特殊对象有几个原因)。

例如,假设我有一个名为Connection的类,它连接到数据库。

[ProtoContract]
public class Connection
{
    [ProtoMember(1)]
    public SqlConnection myConnection {get; set}

    public Connection(String connectionString)
    {
       this.myConnection = new SqlConnection(connectionString);
    }           
}

我想使用protobuf-net序列化这个类,当我尝试正常时:

public void Serialize(Object instance, string path)
{
    using (var stream = new FileStream(path, FileMode.Create))
    {
        Serializer.Serialize(stream, instance);
    }
}

public void someMethod()
{
    Connection p = new Connection("user id=username;" +
    "password=password;server=serverurl;" +
    "Trusted_Connection=yes;" +
    "database=database; " +
    "connection timeout=30");

    Serialize(p);       
}

我得到一个异常(这不是问题)...说我想对待这个对象(SqlConnection)不同。假设我想序列化其connectionString而不是对象本身,所以当我反序列化它时,我可以再次连接到相应的数据库......

我知道我可以做一些类似于另一个类(它实际上将被序列化的类)的东西,它保存有关特殊对象的相应信息(在本例中为connectionString)。但这不是我想要的。

这只是一个例子,我可能有更复杂的对象,我想以不同的方式对待。

因此,我的问题是:有没有办法可以实现这一目标?我读到有关扩展的内容,但我不太了解它们。

提前致谢。

1 个答案:

答案 0 :(得分:0)

目前,这样做的方法是通过“代理人”。基本上,您可以创建类似的类型:

[ProtoContract]
public class SqlConnectionDto
{
    [ProtoMember(1)]
    public string Server { get; set; }
    [ProtoMember(2)]
    public string Database { get; set; }
    // ...

    public static explicit operator SqlConnection(SqlConnectionDto dto)
    {
        if (dto == null) return null;
        var builder = new SqlConnectionStringBuilder
        { 
            DataSource = dto.Server,
            InitialCatalog = dto.Database,
            //...
        };
        return new SqlConnection(builder.ConnectionString);
    }
    public static explicit operator SqlConnectionDto(SqlConnection conn)
    {
        if (conn == null) return null;
        return new SqlConnectionDto
        {
            Server = conn.DataSource,
            Database = conn.Database,
            //...
        };
    }
}

告诉引擎使用它:

RuntimeTypeModel.Default.Add(typeof(SqlConnection), false)
    .SetSurrogate(typeof(SqlConnectionDto));

但是,目前提供对序列化程序的完全控制。扩展值确实是一个选项,但如果没有一个具体的例子,你试图序列化它很难评论这是否合适。