无法使用Mono Cecil设置类型的基类 [英] Cannot set the base class of a type with Mono Cecil

查看:92
本文介绍了无法使用Mono Cecil设置类型的基类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Mono Cecil来操纵DLL.我要做的是将某些类的基本类型从mscorlib.dll设置为System.MarshalByRefObject.我正在使用以下代码.

I am trying to use Mono Cecil to manipulate a DLL. What I want to do is to set the base type of some classes to System.MarshalByRefObject from mscorlib.dll. I am using the following code.

var assembly = AssemblyDefinition.ReadAssembly(inputtarget);
var types = assembly.MainModule.Types;
var myTypesToChange = types.Where(...).Select(t => t);
var baseType = AssemblyDefinition.ReadAssembly(@"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscorlib.dll").MainModule.Types.Where(t => t.Name.Contains("MarshalByRefObject")).Select(t => t).First();
foreach (var myType in myTypesToChange)
{
    myType.BaseType = baseType;
}
assembly.Write(outputtarget);

在输出中未设置基本类型!

In the output the base type is not set!

当我将BaseType设置为从现有程序集中选择的TypeReference时,它是在正确设置基本类型.

When I am setting the BaseType to a TypeReference selected from the existing assembly, it is setting the base type correctly.

我相信我的工作与:

I believe that what I do is very similar to the way it is done as suggested in this reply to a comment about the Code Project article "Reweaving IL code with Mono.Cecil":

是的,您可以重写任何类的基本类型:"

"Yes, you can rewrite the base type of any class:"

var assembly = AssemblyDefinition.ReadAssembly(AssemblyPath); 
var mainModule = assembly.MainModule;

var companyType = mainModule.Types.First(t => t.Name == "Company");
var ownerType = mainModule.Types.First(t => t.Name == "Owner");

ownerType.BaseType = companyType;
assembly.Write(AssemblyPath);

这应该很容易!我在做什么错了?

This should be easy! What I am doing wrong?

推荐答案

问题是未考虑程序集元数据.每个程序集都有元数据,其中包含与程序集引用和类型用法有关的信息.

The problem is that assembly metadata is not taken into account. Each assembly has metadata which contains information related to assembly references and type usages.

您要做的是在mainModule中导入MarshalByRefObject类型:

What you have to do is to import the MarshalByRefObject type in mainModule:

var assembly = assemblyDef.AssemblyDefinition;
var types = assembly.MainModule.Types;
var myTypesToChange = types.Select(t => t);
var baseType = AssemblyDefinition.ReadAssembly(@"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscorlib.dll").MainModule.Types.Where(t => t.Name.Contains("MarshalByRefObject")).Select(t => t).First();
foreach (var myType in myTypesToChange)
{
    myType.BaseType = mainModule.Import(baseType);
}

除了扩展元数据之外,还必须更改构造函数的CIL代码以调用新基类的构造函数,而不是原始基类.

Besides the metadata is extended, CIL code of the constructors have to be changed to invoke a constructor of the new base class instead of the original.

最后,一个建议.我认为MarshalByRefObject的TypeReference可以以更优雅的方式提取:

Finally, a suggestion. I think TypeReference for MarshalByRefObject can be extracted in a more elegant manner:

var baseType = mainModule.Import(typeof (MarshalByRefObject));
for (...)
{
    myType.BaseType = baseType;
}

这篇关于无法使用Mono Cecil设置类型的基类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆