如何通过Mono Cecil获取字段的初始值



我正在尝试使用单cecil将初始值作为dll中的公共字符串。
这是我在课堂库中的代码:

namespace ClassLibrary1
{
    public static class Class1
    {
        public static string testField = "abc";
    }
}

如何获得" ABC"?

我不确定CECIL提供了检索此信息的API,但是由于实例字段是在类型的构造函数 and 静态字段初始化的。在静态构造函数中,您可以寻找所需字段的商店。例如,给定此类:

  .method private hidebysig specialname rtspecialname static 
        void .cctor () cil managed 
    {
        // Method begins at RVA 0x205f
        // Code size 21 (0x15)
        .maxstack 8
        IL_0000: ldstr "Foo"
        IL_0005: stsfld string Program::'value'
        IL_000a: call string Program::MyFunction()
        IL_000f: stsfld string Program::value2
        IL_0014: ret
    } // end of method Program::.cctor

您可以做类似的事情:

using System;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace CecilRetrieveInitializer
{
    class Program
    {
        static Program()
        {
            Console.WriteLine("In cctor..");
        }
        static void Main(string[] args)
        {
            using (var a = AssemblyDefinition.ReadAssembly(typeof(Program).Assembly.Location))
            {
                var t = a.MainModule.GetType("CecilRetrieveInitializer.Program");
                var f = t.Fields.SingleOrDefault(c => c.Name == "value");
                Console.WriteLine(InitialValue(t, f));
                Console.WriteLine(InitialValue(t, t.Fields.SingleOrDefault(c => c.Name == "value2")));
            }
            string InitialValue(TypeDefinition t, FieldDefinition f)
            {
                var cctor = t.Methods.SingleOrDefault(m => m.Name == ".cctor");
                if (cctor == null)
                    throw new Exception("no field initialization...");
                var store = cctor.Body.Instructions.SingleOrDefault(i => i.OpCode == OpCodes.Stsfld && i.Operand == f);
                if (store.Previous.Operand.GetType() != typeof(string))
                    return store.Previous.Operand.ToString();
                return (string) store.Previous.Operand;
            }
        }
        static string MyFunction() => "Bar";
        public static string value = "Foo";
        public static string value2 = MyFunction();
        public const string value3 = "Bar";
    }
}

请记住,该字段可以使用 non const 值初始化,在这种情况下,您可能无法(轻松(检索该值(请参阅 value2 (。

另外,请注意,如果将您的字段声明为 const 您可以使用常数属性:

f = t.Fields.SingleOrDefault(c => c.Name == "value3");
Console.WriteLine(f.Constant);

最新更新