我正在編寫一個XML序列化器,它使用反射來遞歸爬取對象的公共或專用字段以存儲爲XML並稍後重建,同時在臭名昭着的無法串行化的DataTable上測試序列化程序時,以某種方式序列化,然後嘗試重新實例化某種指針,並在此過程中跨過託管/非託管邊界,(幸好)崩潰而不是篡改內存。我需要找到解決這個問題的方法,但是由於我沒有非託管代碼的背景,我有點失落。指針/內存引用的序列化/反序列化
我知道你不能真正序列化指針或引用作爲,是因爲一個指針或引用的值是一個內存地址,你不能指望正確的對象是在經重新該地址從XML實例化指針。據我所知,我需要檢測一個會導致這個問題並忽略它的對象,或者找到並序列化被指向的對象,然後在反序列化之後,對這個對象進行deserailize,然後將指針指向該對象的位置。但我也不知道該怎麼做;我的第一個猜測是過濾Type.IsPointer似乎並沒有阻止這個問題。我可以做什麼?有更好的解決方案嗎?我可以用一些非託管代碼來做到這一點嗎?
上下文:我正在串行器可序列化類型的正常XmlSerializer的不能(IDictionary的,類型的循環引用,等等)。我的序列化器忽略屬性和ISerializeable或IXMLSerializeable的實現;它會遞歸地使用一些規則來序列化所有對象的字段。它可以工作,但它會與某些對象一起進入本機/管理邊界。我沒有使用二進制序列化,因爲我的對象不斷被修改,我不知道如何解決與二進制序列化的對象版本衝突。
編輯:這是當試圖重新實例化「System.Globalization.TextInfo」類時發生崩潰的代碼,我認爲這是深藏在DataTable某處的文化對象的一部分。這些函數以遞歸方式相互調用(始終從ReInstantiateValueInstance開始),直到初始類型參數已被重新實例化。
的管理/本地邊界的例外是在 「bestCtor.Invoke(parameters.ToArray())」,當重新實例System.Globalization.TextInfo(CultureInfo的)拋出
protected object ReCreateTypeWithParameters(Type t)
{
if (t.ToString() == "System.Type") return typeof(object); //we dont know the type of type
var construct = StoreUtilities.GetConstructors(t); //gets any and all constructors for an object
if (construct != null && construct.Count > 0)
{
var leastParams = (from c in construct
select c.GetParameters().Count()).Min();
var bestCtor = (from c in construct
where c.GetParameters().Count() == leastParams
select c).FirstOrDefault(); //the best constructor has the least parameters - less can go wrong
if (bestCtor != null)
{
List<object> parameters = new List<object>();
foreach (var param in bestCtor.GetParameters())
{
parameters.Add(ReInstantiateValueInstance(param.ParameterType));
}
return bestCtor.Invoke(parameters.ToArray()); //pointer types go boom here.
}
}
return null;
}
protected virtual object ReInstantiateValueInstance(Type t)
{
try
{
if (t.ToString() == "System.Type") //we don't know the Type of Type
{
return typeof(object);
}
var construct = StoreUtilities.GetConstructors(t, true); //gets an object's parameterless constructors
if (construct == null && t.IsGenericType) //no constructor, it's generic
{
object generic = ReCreateGenericType(t);
if (generic == null) //if the generic type had no constructor, we use the activator.
{
return Activator.CreateInstance(t);
}
else
{
return generic;
}
}
if (construct == null || construct.Count() == 0) //we have no constuctor. Try and make a placeholder object anyways.
{
return ReCreateTypeWithParameters(t);
}
object o = construct.First().Invoke(null);
return o;
}
catch
{
return null;
}
}
protected object ReCreateGenericType(Type t)
{
try
{
if (Type.IsGenericType != true) return null;
var construct = StoreUtilities.GetConstructors(Type, false);
if (construct != null && construct.Count() > 0)
{
construct = construct.OrderBy(i => i.GetParameters().Count()).ToList();
var tParams = construct[0].GetParameters();
List<object> paramList = new List<object>();
foreach (var p in tParams)
{
if (StoreUtilities.CanStoreAsString(p.ParameterType) == true)
{
object o = Activator.CreateInstance(p.ParameterType);
paramList.Add(o);
}
else
{
paramList.Add(ReInstantiateValueInstance(p.ParameterType));
}
}
return construct[0].Invoke(paramList.ToArray());
}
else
{
return Activator.CreateInstance(t);
}
}
catch
{
return null;
}
}
一些代碼樣本。 – IAbstract 2013-03-07 01:07:29
@Richard你知道你*可以*編輯你的帖子(包括標題),對吧?儘管在這種情況下,其他人已經爲你確定了標題。 – svick 2013-03-07 01:21:35
我同意@IAbstract:你能解釋哪種特定類型是你有問題,還包括你用來序列化它的代碼(理想情況下刪除了不相關的東西)? – svick 2013-03-07 01:24:58