Я не уверен, что Сесил предоставляет API для извлечения этой информации, но поскольку поля экземпляра инициализируются в конструкторе типа и статических полях в статическом конструкторе Вы можете искать магазины в нужном поле. Например, учитывая этот класс:
.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 , вы можете использовать Constant свойство:
f = t.Fields.SingleOrDefault(c => c.Name == "value3");
Console.WriteLine(f.Constant);