C# 当类具有隐式运算符时,使用BinaryFormatter序列化/反序列化

C# 当类具有隐式运算符时,使用BinaryFormatter序列化/反序列化,c#,implicit-conversion,binaryformatter,C#,Implicit Conversion,Binaryformatter,在服务器和客户端之间传输时,我们使用BinaryFormatter将对象转换为字节 我们需要传输的所有类都使用[Serializable]属性,它正常工作。反序列化时,我们还使用自己的SerializationBinder将其映射到正确的对象类型和程序集 但是,当序列化/反序列化任何具有隐式运算符的对象时,我们会遇到问题。 反序列化时,它会根据运算符类型和值执行此操作,因此可能会丢失信息。 例如,一个具有两个属性和一个隐式运算符的类,它将尝试从隐式运算符类型反序列化对象,而来自这两个属性的值似乎

在服务器和客户端之间传输时,我们使用BinaryFormatter将对象转换为字节

我们需要传输的所有类都使用
[Serializable]
属性,它正常工作。反序列化时,我们还使用自己的SerializationBinder将其映射到正确的对象类型和程序集

但是,当序列化/反序列化任何具有隐式运算符的对象时,我们会遇到问题。 反序列化时,它会根据运算符类型和值执行此操作,因此可能会丢失信息。 例如,一个具有两个属性和一个隐式运算符的类,它将尝试从隐式运算符类型反序列化对象,而来自这两个属性的值似乎丢失了

我怎样才能强迫它像其他类一样正常工作?还是我遗漏了什么

更新 在进行进一步研究时,它似乎是一个包装类的组合,该包装类使用返回特定类型的隐式运算符实现ISerializable和child属性

例如:

[Serializable]
    class Dto
    {
        public int MyNumber { get; set; }

        // The implicit operator returning an int will be used when deseralized instead of the complete object
        // If you change it to the operator returning a string, it will not be used at all.
        // Other types like decimal will also trigger the problem, and if multiple are present the int seems to be one that is used.

        public static implicit operator int(Dto dto) => dto.MyNumber;
        //public static implicit operator string(Dto dto) => dto.MyNumber.ToString();
        //public static implicit operator decimal(Dto dto) => (decimal)dto.MyNumber;
    }

    [Serializable]
    class DtoWrapper : ISerializable
    {
        public Dto Dto { get; set; }

        public DtoWrapper() { }

        public DtoWrapper(SerializationInfo info, StreamingContext context)
        {
            Dto = (Dto)info.GetValue(nameof(Dto), typeof(Dto));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue(nameof(Dto), Dto);
        }
    }

首先序列化然后反序列化
DtoWrapper
类的实例时,将出现一个错误,即不能从整数设置Dto属性。

问题的解决方案是使用AddValue()的重载方法,其中显式设置了类型,如下所示:

info.AddValue(nameof(Dto), Dto, typeof(Dto));

这就解决了问题。

要在序列化和反序列化过程中更改类型,需要非常明确的步骤,运算符是不够的。在序列化期间,
SerializationInfo.SetType()
可以更改类型,在反序列化时,
IObjectReference
实现可以返回另一个类型,当然自定义绑定器可以通过存储的程序集和类型名映射到任何类型。我打赌是后者,但没有提供一个可复制的例子,我不能确定。我喜欢得到-1,但对不喜欢的东西没有任何评论。@taffer问题不是我想改变类型。它是由BinaryFormatter自动完成的,尽管我不希望这样做。如果我从类中删除隐式运算符方法,一切都会正常工作。这就是为什么我说需要一个。在那之前,我们可以试着说服对方这是否是由于操作员造成的,但这没有意义。在活页夹中,您可以检查存储的类型,以便在需要映射类型时查看反序列化是否正常。