0

我在程序集中有字节码。我想将此代码复制到另一个程序集。这并不容易,但乍一看我得到了一个很好的副本。我可以复制命名空间、类、自定义属性、字段等。但是我对方法体有疑问。

我知道我可以通过以下方式获取代码:

byte[] ilCode = method.GetMethodBody().GetILAsByteArray();

此外,我知道如何设置新方法 Body:

MethodBuilder methodBuilder = typeBuilder.DefineMethod(method.Name, method.Attributes, method.CallingConvention, method.ReturnType, param.ToArray());
methodBuilder.SetMethodBody(ilCode, method.GetMethodBody().MaxStackSize, sig.GetSignature(), exce, null);

变量定义如下:

  • method : MethodInfo //原始方法
  • param : List //参数类型列表
  • exec : List // 所有异常子句的列表
  • sig : SignatureHelper //不太确定,但与当地人有关

现在我有以下结果:

首先是原始方法:

 .method private hidebysig instance void  onTargetFloorReached() cil managed
{
  // Code size       12 (0xc)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldstr      "TargetFloorReached"
  IL_0006:  call       instance void ['Assembly-CSharp']BaseWeb::CallFunctionWithParameter(string)
  IL_000b:  ret
} // end of method Lift::onTargetFloorReached

现在,我在另一边得到了什么:

.method private hidebysig instance void  onTargetFloorReached() cil managed
{
  // Code size       12 (0xc)
  .maxstack  8
  IL_0000:  ldarg.0
INVALID TOKEN: 0x70000001
  IL_0006:  call        [ERROR: INVALID TOKEN 0x0A00000D] 
  IL_000b:  ret
} // end of method Lift::onTargetFloorReached

我已经尝试加载原始 dll 的每个依赖项,但这不会改变任何东西。

SetMethodBody 方法定义为:

public void SetMethodBody (byte[] il, int maxStack, byte[] localSignature, System.Collections.Generic.IEnumerable<System.Reflection.Emit.ExceptionHandler> exceptionHandlers, System.Collections.Generic.IEnumerable<int> tokenFixups);

没有关于“tokenFixups”的信息。

这些修正是什么?我怎样才能得到它们?或者错误可能在其他地方?

编辑:似乎只有函数调用是无效的。如果我可以从它的字节表示中识别函数,我可以解决这个问题。

4

1 回答 1

0

您应该使用现有的工具,例如https://github.com/dotnet/ILMergehttps://github.com/gluck/il-repack,它们允许您将 dll 和 exe 合并到一个文件中。

至于两次加载同一个类,如果程序集已经加载到应用程序域中,即使程序集版本以某种方式不同(我相信),它也不会被加载两次。所以我不明白这是一个问题。

请参阅加载重复程序集:https://social.msdn.microsoft.com/Forums/vstudio/en-US/9748a274-0925-48a1-8dc7-3214ffe55ff9/prevent-duplicate-dll-from-loading-twice-ccli?论坛=netfxbcl

于 2019-02-22T18:05:45.913 回答