![](/img/trans.png)
[英]How to handle System.OutOfMemoryException when using protobuf-net?
[英]How does protobuf-net handle readonly fields?
我使用protobuf-net來序列化/反序列化我的數據。
我有一些相當簡單的類,所以這不是真正的問題。
據我所知,protobuf-net使用IL生成來創建序列化/反序列化代碼。 雖然我的模型中只有字段,但我想知道用IL寫這樣一個字段怎么可能? 我可以清楚地看到它運作良好,但我不知道為什么......
我試圖在代碼中窺探它,但它有點太復雜了。
我自己嘗試生成此類代碼總是會導致IL驗證程序錯誤。
實際上,我無法讓它失敗 - 至少,在內存中生成時。
讓我們簡單地開始,使用public readonly
字段(因此我們不會破壞任何可訪問性規則); 我的第一次嘗試如下,它工作正常:
using System;
using System.Reflection;
using System.Reflection.Emit;
class Foo
{
public readonly int i;
public int I { get { return i; } }
public Foo(int i) { this.i = i; }
}
static class Program
{
static void Main()
{
var setter = CreateWriteAnyInt32Field(typeof(Foo), "i");
var foo = new Foo(123);
setter(foo, 42);
Console.WriteLine(foo.I); // 42;
}
static Action<object, int> CreateWriteAnyInt32Field(Type type, string fieldName)
{
var field = type.GetField(fieldName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var method = new DynamicMethod("evil", null,
new[] { typeof(object), typeof(int) });
var il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, type);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Stfld, field);
il.Emit(OpCodes.Ret);
return (Action<object, int>)method.CreateDelegate(typeof(Action<object, int>));
}
}
它變得有趣的唯一一次是該字段是private
:
private readonly int i;
上面的代碼然后給出了那么模糊:
操作可能會破壞運行時的穩定性。
但是我們通過假裝該方法在字段的聲明類型中來解決這個問題:
var method = new DynamicMethod("evil", null,
new[] { typeof(object), typeof(int) }, field.DeclaringType);
通過啟用skipVisibility
可以完成其他一些內部檢查:
var method = new DynamicMethod("evil", null,
new[] { typeof(object), typeof(int) }, field.DeclaringType, true);
但請注意,如果生成獨立程序集,並非所有這些都可行。 在創建實際dll時,您將遵循更高的標准。 因此, precompiler
工具(預生成程序集)無法處理與內存中元編程代碼完全相同的場景。
由於我對這個討論很感興趣,我嘗試過Marc Gravell的示例代碼,並且它在MS .NET 4.0上拋出了VerificationException
。
我已經設法使它工作但我需要使用DynamicMethod
構造函數,並將owner
參數設置為field.DeclaringType
即使在public i
字段的情況下也是如此。 在這種情況下, SkipVisibility
參數似乎是多余的。
PS。 我相信這個條目應該是一個評論,但由於缺乏代表,我無法評論其他人的答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.