我使用BinaryFormatter
序列化大型复杂对象,并且某些属性的序列化导致SerializationException
。如何获取有关哪些属性导致错误的信息?
当然,我可以获取无法序列化的类型的名称,但是我找不到包含该类型实例的属性。
异常消息如下:
Type "MyType" from assembly "MyAssembly" is not marked as serializable.
此类型的实例不应存在于序列化的对象中,我找不到包含它的属性。
要序列化我使用这个简单的代码(其中数据是我的复杂类型的实例):
...
var str = new MemoryStream();
var bf= new BinaryFormatter();
bf.Serialize(stream, data);
...
答案 0 :(得分:1)
好吧,使用反射找到了对象
private bool TrySerialize(object obj)
{
if (obj == null)
return true;
var stream = new MemoryStream();
var bf = new BinaryFormatter();
try
{
bf.Serialize(stream, obj);
}
catch (SerializationException)
{
return false;
}
return true;
}
private string FindObject(Stack<object> self, Type typeToFind, string path)
{
var _self = self.Peek();
if (self.Where(x => x.Equals(_self)).Count() > 1) return null;
foreach (var prop in _self.GetType().GetMembers().Where(x => !x.GetCustomAttributes(true).Any(y => y is XmlIgnoreAttribute)))
{
switch (prop.MemberType)
{
case System.Reflection.MemberTypes.Property:
{
var line = string.Format("{0}::{1}", path, prop.Name);
var _prop = prop as PropertyInfo;
if (_prop.GetIndexParameters().Count() > 0) break;
if (typeToFind.IsAssignableFrom(_prop.PropertyType))
return line;
if (_prop.PropertyType.IsPrimitive || _prop.PropertyType == typeof(DateTime) || _prop.PropertyType == typeof(string))
continue;
var subInst = _prop.GetValue(_self, new object[0]);
if (subInst == null)
continue;
if (!TrySerialize(subInst))
{
System.Diagnostics.Debugger.Log(0,"",string.Format("Cannot serialize {0}\n", line));
}
self.Push(subInst);
var result = FindObject(self, typeToFind, line);
self.Pop();
if (result != null)
return result;
}
break;
case System.Reflection.MemberTypes.Field:
{
var line = string.Format("{0}::*{1}", path, prop.Name);
var _prop = prop as FieldInfo;
if (typeToFind.IsAssignableFrom(_prop.FieldType))
return line;
if (_prop.FieldType.IsPrimitive || _prop.FieldType == typeof(DateTime) || _prop.FieldType == typeof(string))
continue;
var subInst = _prop.GetValue(_self);
if (subInst == null)
continue;
if (!TrySerialize(subInst))
{
System.Diagnostics.Debugger.Log(0, "", string.Format("Cannot serialize field {0}\n", line));
}
self.Push(subInst);
var result = FindObject(self, typeToFind, line);
self.Pop();
if (result != null)
return result;
}
break;
case System.Reflection.MemberTypes.Event:
{
var line = string.Format("{0}::!{1}", path, prop.Name);
var _prop = prop as EventInfo;
if (typeToFind.IsAssignableFrom(_prop.EventHandlerType))
return line;
var field = _self.GetType().GetField(_prop.Name,
BindingFlags.NonPublic |BindingFlags.Instance |BindingFlags.GetField);
if (field!=null && !field.GetCustomAttributes(true).Any(x=>x is NonSerializedAttribute)
&& !TrySerialize(field.GetValue(_self)))
{
System.Diagnostics.Debugger.Log(0, "", string.Format("Cannot serialize event {0}\n", line));
}
}
break;
case System.Reflection.MemberTypes.Custom:
{
}
break;
default: break;
}
}
if (_self is IEnumerable)
{
var list = (_self as IEnumerable).Cast<object>();
var index = 0;
foreach (var item in list)
{
index++;
self.Push(item);
var result = FindObject(self, typeToFind, string.Format("{0}[{1}]", path, index));
self.Pop();
if (result != null)
return result;
}
}
return null;
}
以这种方式使用电话:
string result = FindObject(new Stack<object>(new object[] { instanceToSearchIn }), typeof(MyType), "[myself]");
因此我得到了:
[myself]::RootSection::Children[0]::Children[0]::Item
<强>更新强>
此代码现在还测试成员序列化
答案 1 :(得分:0)
您需要在您尝试序列化的类上添加Serializable标记。
这是一个例子。我有一个类名Point2D,它有一些属性和序列化标签。
[Serializable]
public class Point2D
{
[XmlAttribute]
public double X { get; set; }
[XmlAttribute]
public double Y { get; set; }
}
这是序列化代码。
var point2D = new Point2D { X = 2, Y = 3 };
var stream = new MemoryStream();
var bf= new BinaryFormatter();
bf.Serialize(stream, point2D);