【问题标题】:In Binary Serialization(C#) how to skip non serializable fields in a Serializable Object?在二进制序列化(C#)中,如何跳过可序列化对象中的不可序列化字段?
【发布时间】:2015-11-17 11:31:09
【问题描述】:

我有一个标有 [Serializable] 属性的类。这个类有许多不同类型的字段。此类引用的大多数类型都具有 [Serializable] 属性,但其中一些没有此属性。

在上述情况下,二进制序列化失败,这是意料之中的。

我已经简化了上述描述中的问题。实际上,我正在处理一个大型企业应用程序,它具有复杂的对象层次结构,并且深入到层次结构中,有一些窗口类型无法序列化并且二进制序列化失败。我想要一个解决方案。

是否有自定义二进制序列化器可以跳过无法序列化的字段?

注意:我知道这个概念: How do you identify the field that is causing binary serialization to fail in .NET?

我正在寻找更优雅的解决方案。

【问题讨论】:

  • JavaScriptSerializer 是解决方案。像魅力一样工作。

标签: .net exception


【解决方案1】:

您可以在字段上添加[NonSerialized] 属性,以在您确定它无法序列化后完全跳过它。

如果它的类型在你无法控制的层次结构中更进一步导致这种情况,那么我的建议是复制有问题的类/结构的结构 sans-unserializable-fields 并使用类似 automapper将值深度复制到新类中,然后序列化最终结果。

【讨论】:

  • 我正在寻找一种解决方案,它可以在运行时将 [NonSerialized] 属性添加到层次结构中的特定字段(我们控制的源而不是 .net 类型)并进一步跳过序列化向下层级。
【解决方案2】:

我编写了一个示例程序来帮助我解决这个问题。

想象一个结构如下的对象: Sample Object Structure

class Program
{
    static void Main(string[] args)
    {
        StringBuilder sb = new StringBuilder();
        Root rootObject = new Root();

        FindNonSerializableFields(rootObject, rootObject.GetType().Name, sb);
        string unserializedFields = sb.ToString();
        bool isObjectSerializable = string.IsNullOrEmpty(unserializedFields);
        Console.WriteLine("Is object Serializable? : {0}", isObjectSerializable);
        if (!isObjectSerializable)
        {
            Console.WriteLine("Unserializable Fields:");
            Console.WriteLine(unserializedFields);
        }
    }

    static void FindNonSerializableFields(object obj, string lineage, StringBuilder sb, uint stopAtDepth = 7)
    {
        if (lineage.Count(f => f == '»') >= stopAtDepth)
        {
            return;
        }

        if (!IsObjectBinarySerializable(obj))
        {
            sb.AppendLine(lineage);
            var fields = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            foreach (var field in fields)
            {
                object fieldObject = field.GetValue(obj);
                if (fieldObject != null && !Attribute.IsDefined(field, typeof(NonSerializedAttribute)))
                {
                    FindNonSerializableFields(fieldObject, lineage + "»" + fieldObject.GetType().Name, sb);
                }
            }
        }
    }

    static bool IsObjectBinarySerializable(object obj)
    {
        try
        {
            using (MemoryStream memorystream = new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(memorystream, obj);
            }
        }
        catch(SerializationException)
        {
            return false;
        }

        return true;
    }
}

[Serializable]
class Root
{
    public L1B1 l1b1 = new L1B1();
    private L1B2 l1b2 = new L1B2();
    protected L1B3 l1b3 = new L1B3();
}

[Serializable]
class L1B1
{
    public L2B1 l2b1 = new L2B1();
}

[Serializable]
class L1B2
{
    private L2B2 l2b2 = new L2B2();
}

[Serializable]
class L1B3
{
    protected L2B3 l2b3 = new L2B3();
}

//[Serializable]
class L2B1
{
    protected Leaf_B1 leaf_b1 = new Leaf_B1();
}

[Serializable]
class L2B2
{
    public Leaf_B2 leaf_b2 = new Leaf_B2();
}

[Serializable]
class L2B3
{
    private Leaf_B3 leaf_b3 = new Leaf_B3();
}

[Serializable]
class Leaf_B1
{
    [NonSerialized]
    private int var1 = 10;
    public string var2 = "string_Leaf_B1";
    public bool var3 = true;
}

[Serializable]
class Leaf_B2
{
    private int var1 = 10;
    [NonSerialized]
    public string var2 = "string_Leaf_B2";
    public bool var3 = true;
}

//[Serializable]
class Leaf_B3
{
    private int var1 = 10;
    public string var2 = "string_Leaf_B3";
    [NonSerialized]
    public bool var3 = true;
}

样本输出:

对象可以序列化吗? : 错误

不可序列化字段:

根»L1B1

根»L1B1»L2B1

这样我就知道序列化在哪里中断了。

在编写此示例时,我没有考虑性能或任何编码标准。 很高兴看到有人提出更好的解决方案。

【讨论】:

    猜你喜欢
    • 2016-09-25
    • 1970-01-01
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    • 2011-06-08
    • 2014-01-30
    • 2017-01-08
    • 1970-01-01
    相关资源
    最近更新 更多