我有一个标有[Serializable]属性的类。这个类有很多不同类型的字段。此类引用的大多数类型都具有[Serializable]属性,但其中一些不具备此属性。
二进制序列化在上述场景中失败,这是预期的。
我在上面的描述中简化了问题。实际上,我正在处理一个具有复杂对象层次结构的大型企业应用程序,并且在层次结构深处有一些无法序列化的窗口类型,二进制序列化失败。我想要一个解决方案。
是否有自定义二进制序列化程序可以跳过无法序列化的字段?
注意:我知道这个概念: How do you identify the field that is causing binary serialization to fail in .NET?
我正在寻找更优雅的解决方案。
答案 0 :(得分:0)
您可以在字段上添加[NonSerialized]
属性,以便在您确定无法序列化后将其完全跳过。
如果它在层次结构中的类型更远,你无法控制它导致这个,那么我建议的是复制有问题的类/结构的结构sans-unserializable-fields并使用像automapper这样的东西将值深度复制到新类,然后序列化最终结果。
答案 1 :(得分:0)
我写了一个帮助我解决这个问题的示例程序。
想象一个像这样构造的对象: 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
这样我知道序列化的确切位置。
在编写此示例时,我没有考虑性能或任何编码标准。 很高兴看到有人提出更好的解决方案。