我正在尝试使用单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);