.NET 使用ILPack组件将程序集保存成dll

本文介绍使用ILPack组件将程序集保存成dll

.net core 版本不再支持使用 AssemblyBuilder.Save 的方式将程序集保存成dll

具体讨论 https://github.com/dotnet/runtime/issues/15704

可以使用ILPack组件将程序集保存成dll,以下为官方案例

var assembly = Assembly.GetAssembly(t);
var generator = new Lokad.ILPack.AssemblyGenerator();

// for ad-hoc serialization
var bytes = generator.GenerateAssemblyBytes(assembly);

// direct serialization to disk
generator.GenerateAssembly(assembly, "/path/to/file");

实际应用

在实际应用中可以使用该组件进行对编写的动态代码进行反编译验证逻辑,以下为具体案例

  1. 首先写了一个较为复杂的IL方法
        public static void CreateEscapeQuotesMethod()
        {
            var method = new DynamicMethod("EscapeQuotes", typeof(string), new Type[1] { typeof(string) });
            IL_EscapeQuotes(method.GetILGenerator());
            ILPackVerification.Save(method, IL_EscapeQuotes);
            var methodDelegate = method.CreateDelegate<Func<string, string>>();
            string result = (string)methodDelegate.DynamicInvoke("dafdasf");
            Console.WriteLine(result);
            static void IL_EscapeQuotes(ILGenerator il)
            {
                il.DeclareLocal(typeof(string));
                var lb = il.DefineLabel();
                il.Emit(OpCodes.Nop);
                il.Emit(OpCodes.Ldarg_0);//将第一个参数放置到堆栈上
                il.Emit(OpCodes.Ldstr, "\"");
                il.Emit(OpCodes.Ldstr, "\\\"");
                il.Emit(OpCodes.Call, typeof(string).GetMethod(nameof(string.Replace), new Type[2] { typeof(string), typeof(string) }));
                il.Emit(OpCodes.Stloc_0);//将栈顶元素存储到本地变量0中
                il.Emit(OpCodes.Br_S, lb);
                il.MarkLabel(lb);
                il.Emit(OpCodes.Ldloc_0);// 将本地变量表中索引为0的变量加载到堆栈中
                il.Emit(OpCodes.Ret);
            }
        }
  1. 使用ILPack将程序集转存成dll文件
    public class ILPackVerification
    {
        public static ModuleBuilder Builder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("ILTest.Dynamic"), AssemblyBuilderAccess.Run).DefineDynamicModule("TestDynamicModule");
        public static void Save(DynamicMethod method, Action<ILGenerator> setIL)
        {
            var type = Builder.DefineType("ILPackVerificationClass", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed);
            var newMethod = type.DefineMethod(method.Name, method.Attributes, method.ReturnType, method.GetParameters().Select(v => v.ParameterType).ToArray());
            setIL(newMethod.GetILGenerator());
            Console.WriteLine("方法:" + method.Name + "开始保存...");

            Save(type.CreateType());
        }

        public static void Save(Type type)
        {
            var assembly = Assembly.GetAssembly(type);
            Console.WriteLine("类:" + type.Name + "开始保存...");

            Save(assembly);
        }

        public static void Save(Assembly dynamicAssembly)
        {
            var generator = new Lokad.ILPack.AssemblyGenerator();

            generator.GenerateAssembly(dynamicAssembly, "/dils.dll");
            Console.WriteLine("DLL输出成功!");
        }
    }
  1. 生成dll

  2. 使用ILSpay工具查看反编译之后的代码

总结

通过以上方式能够将动态程序集保存成dll文件,再通过反编译工具查看代码的逻辑,此方式可以用来验证IL代码是否编写正确(其中一种方法)。

源码地址

https://github.com/Impartsoft/ILLesson

posted @ 2023-06-13 22:20  Iannnnnnnnnnnnn  阅读(85)  评论(0编辑  收藏  举报