猿问

C# 在运行时以编程方式编辑我的 .NET 程序集

我有一个由我构建的 .NET 程序集,但希望能够在运行时使用一些较小但任意的属性更改文件重写 .DLL 。具体来说,我希望能够更改类属性的属性,以便我可以根据情况自定义二进制文件。


为了说明,我想实现编辑从代码生成的程序集的效果


[SomeAttribute("Name")]

public class MyClass{

    ...

这样新组件在功能上与


[SomeAttribute("Custom Name")]

public class MyClass{

    ...

这个“自定义名称”可以是任何东西(在运行时确定)。这可以在运行时完成吗?


实际 .DLL 需要修改的原因是因为它会被一个无法确定运行时信息的单独进程加载(我不控制这个进程)。


到目前为止的实验表明,如果新的“自定义名称”与原始名称的长度相同,它似乎可以工作,但否则就不行(即使您编辑指定长度的前一个字节;大概文件中某处存储了偏移量)。


编辑:忘了提,解决方案也需要在 .NET 2 框架下。


翻过高山走不出你
浏览 187回答 3
3回答

缥缈止盈

不清楚你真正想做什么(XY 问题?)尽管如此,如果你想修改一个程序集,你通常使用Mono.Cecil,它自我描述为:你可以加载现有的托管程序集,浏览所有包含的类型,动态修改它们并将修改后的程序集保存回磁盘。.请注意,属性可以包含作为参数传递的数据之上的额外数据:public class MyAttribute : Attribute{&nbsp; &nbsp; public MyAttribute(string str)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; argument = str;&nbsp; &nbsp; }&nbsp; &nbsp; private string argument;&nbsp; &nbsp; public string Argument { get; }&nbsp; &nbsp; public string AssemblyName&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; get&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Assembly.GetEntryAssembly().FullName;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}[MyAttribute("Hello")]class Program{&nbsp; &nbsp; static void Main(string[] args)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var attr = typeof(Program).GetCustomAttribute<MyAttribute>();&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine(attr.Argument);&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine(attr.AssemblyName);&nbsp; &nbsp; }}

慕码人8056858

使用来自@xanatos 的非常有用的建议,我提出了这个解决方案:在 .NET 2 下,您可以安装包 Mono.Cecil 0.9.6.1。代码如下:AssemblyDefinition assbDef = AssemblyDefinition.ReadAssembly("x.dll");TypeDefinition type = assbDef.MainModule.GetType("NameSpace.MyClass").Resolve();foreach (CustomAttribute attr in type.CustomAttributes){&nbsp; &nbsp; TypeReference argTypeRef = null;&nbsp; &nbsp; int? index = null;&nbsp; &nbsp; for (int i = 0; i < attr.ConstructorArguments.Count; i++)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; CustomAttributeArgument arg = attr.ConstructorArguments[i];&nbsp; &nbsp; &nbsp; &nbsp; string stringValue = arg.Value as string;&nbsp; &nbsp; &nbsp; &nbsp; if (stringValue == "Name")&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; argTypeRef = arg.Type;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; index = i;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; if (index != null)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; attr.ConstructorArguments[(int)index] = new CustomAttributeArgument(argTypeRef, newName);&nbsp; &nbsp; }}&nbsp; &nbsp;&nbsp;assbDef.Write("y.dll");这将在程序集中搜索任何具有 value 的属性参数"Name"并将它们的值替换为newName.
随时随地看视频慕课网APP
我要回答