簡體   English   中英

如何在運行時修改 .Net 程序集並保留這些更改

[英]How To Modify .Net Assembly At Runtime And Keep These Changes

你好,

我只是問在 C#.Net 中是否有一種方法可以在運行時修改程序集,如果我有一個此類,我的意思是什么

public static class TimesTracker
{
    public static int Rest = 3;
}

現在,我需要在運行時將Rest更改為2但保留這些更改。

所以,下次我打開我的程序時,我發現Rest=2

我知道,我可以使用配置文件,DB,...但我只是詢問這種可能性

背景

我知道在運行時替換方法實現,也知道在運行時使用 Roslyn 調用/編譯字符串代碼

有趣的。 但是我想不出任何用例。

我之前在 MSBuild 目標中使用Mono.Cecil來動態修改程序集並保存回磁盤。

以下是如何完成您所要求的示例:

var filePath = "Assembly path";
var updatedFilePath = "Updated assembly path";

// Read assembly
using (var assembly = AssemblyDefinition.ReadAssembly(filePath))
{
    // Find type TimesTracker. This example was done in LINQPad, so TimesTracker is nested type inside UserQuery
    var type = assembly.MainModule.Types.SelectMany(t => t.NestedTypes).First(td => td.Name == "TimesTracker");
    // Find static constructor
    var cctor = type.Methods.First(md => md.Name == ".cctor");

    // Get IL
    var il = cctor.Body.GetILProcessor();

    // The IL of Rest = 3 is:
    // IL_0000: ldc.i4.3
    // IL_0001: stsfld int32 UserQuery / TimesTracker::Rest
    var op = il.Body.Instructions.First(i => i.OpCode == OpCodes.Ldc_I4_3);
    // Replace 3 with 7
    var newOp = il.Create(OpCodes.Ldc_I4_7);
    il.Replace(op, newOp);

    // Write updated to another assembly file
    assembly.Write(updatedFilePath);
}

// Load updated assembly into AppDomain
var updatedAssembly = Assembly.LoadFile(updatedFilePath);
// Use reflection to get value of Rest
var updatedType = updatedAssembly.DefinedTypes.First(t => t.Name.Contains("TimesTracker"));
var field = updatedType.GetField("Rest", BindingFlags.Public | BindingFlags.Static);

// value is now 7
var value = (int)field.GetValue(null);

注意上面的代碼只能修改:

public class TimesTracker
{ 
    public static int Rest = 3;
}

但是,因為 C# 不允許重新加載程序集,除非卸載整個AppDomain ,所以使用/加載更新的程序集將是一個挑戰。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM