簡體   English   中英

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM