我正在尝试使用Mono Cecil获取DLL中公共字段的字符串形式的初始值。
这是我在类库中的代码:
namespace ClassLibrary1
{
public static class Class1
{
public static string testField = "abc";
}
}
如何获取“ abc”?
答案 0 :(得分:2)
我不确定Cecil是否提供API来检索此信息,但是由于实例字段是在静态构造函数中的类型的构造函数和静态字段中初始化的, / strong>,您可以查找所需字段的商店。例如,给定此类:
.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";
}
}
请记住,该字段可能会使用非常量值进行初始化,在这种情况下,您可能无法(轻松地)检索该值(请参阅 value2 >)。
此外,请注意,如果您将字段声明为 const ,则可以使用 Constant 属性:
f = t.Fields.SingleOrDefault(c => c.Name == "value3");
Console.WriteLine(f.Constant);