C# 当您没有';你没有这个类的源代码吗?

C# 当您没有';你没有这个类的源代码吗?,c#,.net,serialization,binary,binary-serialization,C#,.net,Serialization,Binary,Binary Serialization,我正在使用BinaryFormatter对C#中的一些对象进行二进制序列化。但是,有些对象包含我通过DLL访问的类,并且没有其源代码,因此我无法使用Serializable属性标记它们。有没有一种简单的方法来序列化它们?我有一个解决方法,它包括获取classNoSource并创建一个新的classSerializableNoSource,构造函数获取一个NoSource对象并从中提取我需要的所有信息,但它很粗糙。有更好的选择吗?我认为更干净的方法是实现ISerializable接口,并管理自己的

我正在使用
BinaryFormatter
对C#中的一些对象进行二进制序列化。但是,有些对象包含我通过DLL访问的类,并且没有其源代码,因此我无法使用
Serializable
属性标记它们。有没有一种简单的方法来序列化它们?我有一个解决方法,它包括获取class
NoSource
并创建一个新的class
SerializableNoSource
,构造函数获取一个
NoSource
对象并从中提取我需要的所有信息,但它很粗糙。有更好的选择吗?

我认为更干净的方法是实现ISerializable接口,并管理自己的序列化和反向过程。 在MSDN中,我们可以找到:

序列化操作完成后,无法将其添加到类中 编译


您可以使用将
[SerializableAttribute]
添加到类中,但如果有其他方法可以实现所需的结果,我不会这样做。

我同意@Servy,如果类的作者没有预料到它会被序列化,那么您不应该尝试直接序列化它。因此,从架构的角度来看,您做的事情是正确的。为了使您当前的方法更少,“HACKY”考虑对包含非序列化对象的引用的类的实现。

< P>创建一个新类,继承没有序列化属性标记的现有类,并实现ISEIALIALION接口。 如果该类是密封的,那么您可以使用Json.NET,然后将其转换为二进制,反之亦然(这太浪费时间了,如果没有其他帮助,请使用它:)。

您可以创建序列化代理

假设我们在引用的程序集中定义了一个类,但我们无法控制该类,该类如下所示:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public DriversLicense License;
}


// An instance of this type will be part of the object graph and will need to be 
// serialized also.
public class DriversLicense
{
    public string Number { get; set; }
}
为了序列化此对象,需要为对象图中的每种类型定义序列化代理

要创建序列化代理,只需创建实现接口的类型:

public class PersonSurrogate : ISerializationSurrogate
{
    /// <summary>
    /// Manually add objects to the <see cref="SerializationInfo"/> store.
    /// </summary>
    public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
    {
        Person person = (Person) obj;
        info.AddValue("Name", person.Name);
        info.AddValue("Age", person.Age);
        info.AddValue("License", person.License);
    }

    /// <summary>
    /// Retrieves objects from the <see cref="SerializationInfo"/> store.
    /// </summary>
    /// <returns></returns>
    public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        Person person = (Person)obj;
        person.Name = info.GetString("Name");
        person.Age = info.GetInt32("Age");
        person.License = (DriversLicense) info.GetValue("License", typeof(DriversLicense));
        return person;
    }
}

public class DriversLicenseSurrogate : ISerializationSurrogate
{
    /// <summary>
    /// Manually add objects to the <see cref="SerializationInfo"/> store.
    /// </summary>
    public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
    {
        DriversLicense license = (DriversLicense)obj;
        info.AddValue("Number", license.Number);
    }

    /// <summary>
    /// Retrieves objects from the <see cref="SerializationInfo"/> store.
    /// </summary>
    /// <returns></returns>
    public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        DriversLicense license = (DriversLicense)obj;
        license.Number = info.GetString("Number");
        return license;
    }
}
使用序列化代理绝非易事,当您试图序列化的类型具有需要序列化的私有和受保护字段时,它实际上可能会变得非常冗长


但是,由于您已经在手动序列化所需的值,我认为这不是问题。使用代理是处理此类场景的一种更统一的方法,应该会让您感觉更舒服。

我知道这是一个老问题,但我最近发现需要序列化/反序列化DTO,因为出于性能原因,我们无法控制二进制格式的源代码。设法找到了许多替代的二进制序列化程序,如ZeroFormatter和Protobuf,但它们都需要用属性修饰DTO或定义模式


这让我走上了创建自己的二进制序列化程序的道路,它是二进制格式JSON序列化程序的快速替代品,您可能会发现它很有用:

记录在案,将对象封装在另一个知道如何序列化自身的对象中,以及与封装对象之间的转换在我看来并不困难,这完全合适。现在,可能会有一些更光滑或更好的东西,但我不认为您当前的方法存在根本缺陷。这似乎是真正序列化未标记为“代码> [可序列化]的未拥有类的教科书答案。如果您想了解更多信息,可以阅读《运行时序列化》的第23章。也可以在MSDN上找到这篇相关文章:“但是,有些对象包含我通过DLL访问的类,并且没有源代码”你可以创建你自己的类,它可以和你没有源代码的对象有相同的属性吗?或者扩展它??扩展不起作用,复制属性。。。那和他现在的情况一样
private static void SerializePerson(Person person)
{
    if (person == null)
        throw new ArgumentNullException("person");

    using (var memoryStream = new MemoryStream())
    {
        //Configure our surrogate selectors.
        var surrogateSelector = new SurrogateSelector();
        surrogateSelector.AddSurrogate(typeof (Person), new StreamingContext(StreamingContextStates.All),
                                       new PersonSurrogate());
        surrogateSelector.AddSurrogate(typeof (DriversLicense), new StreamingContext(StreamingContextStates.All),
                                       new DriversLicenseSurrogate());

        //Serialize the object
        IFormatter formatter = new BinaryFormatter();
        formatter.SurrogateSelector = surrogateSelector;
        formatter.Serialize(memoryStream, person);

        //Return to the beginning of the stream
        memoryStream.Seek(0, SeekOrigin.Begin);

        //Deserialize the object
        Person deserializedPerson = (Person) formatter.Deserialize(memoryStream);
    }
}