Информация об изменениях

Сообщение Re[5]: Удобный способ внесения изменений в чужую C#-библиоте от 26.04.2016 1:36

Изменено 26.04.2016 2:20 Albeoris

A>Буду чистить этот зоопарк. Посмотрим, может быть случится чудо и после чистки проблема исчезнет, ведь эта сборка теперь будет ссылаться напрямую на мою.

Нашёл такой вот монстоузный код:
https://groups.google.com/forum/#!msg/mono-cecil/3D0RLfvN054/0Fxv1g0fYk8J

Но после обработки получаю ошибку
[quote]"Member '{0}' is declared in another module and needs to be imported"
в Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
в Mono.Cecil.SignatureWriter.WriteTypeSignature(TypeReference type)
в Mono.Cecil.SignatureWriter.WriteGenericInstanceSignature(IGenericInstance instance)
в Mono.Cecil.MetadataBuilder.GetMethodSpecSignature(MethodSpecification method_spec)
в Mono.Cecil.MetadataBuilder.CreateMethodSpecRow(MethodSpecification method_spec)
в Mono.Cecil.MetadataBuilder.GetMethodSpecToken(MethodSpecification method_spec)
в Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
в Mono.Cecil.Cil.CodeWriter.WriteOperand(Instruction instruction)
в Mono.Cecil.Cil.CodeWriter.WriteInstructions()
в Mono.Cecil.Cil.CodeWriter.WriteResolvedMethodBody(MethodDefinition method)
в Mono.Cecil.Cil.CodeWriter.WriteMethodBody(MethodDefinition method)
в Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method)
в Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type)
в Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
в Mono.Cecil.MetadataBuilder.AddTypeDefs()
в Mono.Cecil.MetadataBuilder.BuildTypes()
в Mono.Cecil.MetadataBuilder.BuildModule()
в Mono.Cecil.ModuleWriter.<BuildMetadata>b__0(MetadataBuilder builder, MetadataReader _)
в Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
в Mono.Cecil.ModuleWriter.WriteModuleTo(ModuleDefinition module, Stream stream, WriterParameters parameters)
в Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
в Mono.Cecil.AssemblyDefinition.Write(String fileName)[/quote]

Проблема в том, что в процессе замены инструкций я добавил проверку после каждой:
MemberReference op = instructions[i].Operand as MemberReference;
if (op != null)
{
    if (op.Module != module)
        throw new InvalidCastException();
}


И я, честно говоря, не понимаю, по какой причине у меня эта проверка проходит нормально, а Mono падает — откуда он берёт этот проклятущий MemberReference с левым модулем?

Хотя это явно только начало — автор игноирует Generic'и, аттрибуты, исключения, но это можно будет дописать по мере возникновения проблем.

---
Ох, блин...
if (member == null || member.Module != this.module)
throw MetadataBuilder.CreateForeignMemberException(member);

Возможно, причина в том, что member == null

---
Тьфу, пропасть!
Точно. ldfld null
Буду разбираться — в какой момент (и где) я его потерял...
---
Ура! Прорвался.
НЕЛЬЗЯ удалять из сборки старый тип, до того, как все ссылки на него не будут заменены на новый.
Как и ожидалось, впилился в Generic'и, но это прогресс. Едем дальше!

   в Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
   в Mono.Cecil.SignatureWriter.WriteTypeSignature(TypeReference type)
   в Mono.Cecil.SignatureWriter.WriteGenericInstanceSignature(IGenericInstance instance)
   в Mono.Cecil.MetadataBuilder.GetMethodSpecSignature(MethodSpecification method_spec)
   в Mono.Cecil.MetadataBuilder.CreateMethodSpecRow(MethodSpecification method_spec)
   в Mono.Cecil.MetadataBuilder.GetMethodSpecToken(MethodSpecification method_spec)
   в Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
   в Mono.Cecil.Cil.CodeWriter.WriteOperand(Instruction instruction)
   в Mono.Cecil.Cil.CodeWriter.WriteInstructions()
   в Mono.Cecil.Cil.CodeWriter.WriteResolvedMethodBody(MethodDefinition method)
   в Mono.Cecil.Cil.CodeWriter.WriteMethodBody(MethodDefinition method)
   в Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method)
   в Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type)
   в Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
   в Mono.Cecil.MetadataBuilder.AddTypeDefs()
   в Mono.Cecil.MetadataBuilder.BuildTypes()
   в Mono.Cecil.MetadataBuilder.BuildModule()
   в Mono.Cecil.ModuleWriter.<BuildMetadata>b__0(MetadataBuilder builder, MetadataReader _)
   в Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
   в Mono.Cecil.ModuleWriter.WriteModuleTo(ModuleDefinition module, Stream stream, WriterParameters parameters)
   в Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
   в Mono.Cecil.AssemblyDefinition.Write(String fileName)
A>Буду чистить этот зоопарк. Посмотрим, может быть случится чудо и после чистки проблема исчезнет, ведь эта сборка теперь будет ссылаться напрямую на мою.

Нашёл такой вот монстоузный код:
https://groups.google.com/forum/#!msg/mono-cecil/3D0RLfvN054/0Fxv1g0fYk8J

Приплыли:
Ну и как мне патчить UnresolvedMethodBody?
   в Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
   в Mono.Cecil.Cil.CodeReader.PatchRawCode(ByteBuffer buffer, Int32 code_size, CodeWriter writer)
   в Mono.Cecil.Cil.CodeReader.PatchRawFatMethod(ByteBuffer buffer, MethodSymbols symbols, CodeWriter writer, MetadataToken& local_var_token)
   в Mono.Cecil.Cil.CodeReader.PatchRawMethodBody(MethodDefinition method, CodeWriter writer, MethodSymbols& symbols)
   в Mono.Cecil.Cil.CodeWriter.WriteUnresolvedMethodBody(MethodDefinition method)
   в Mono.Cecil.Cil.CodeWriter.WriteMethodBody(MethodDefinition method)
   в Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method)
   в Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type)
   в Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
   в Mono.Cecil.MetadataBuilder.AddNestedTypes(TypeDefinition type)
   в Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
   в Mono.Cecil.MetadataBuilder.AddTypeDefs()
   в Mono.Cecil.MetadataBuilder.BuildTypes()
   в Mono.Cecil.MetadataBuilder.BuildModule()
   в Mono.Cecil.ModuleWriter.<BuildMetadata>b__0(MetadataBuilder builder, MetadataReader _)
   в Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
   в Mono.Cecil.ModuleWriter.WriteModuleTo(ModuleDefinition module, Stream stream, WriterParameters parameters)
   в Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
   в Mono.Cecil.AssemblyDefinition.Write(String fileName)
   в Memoria.Patcher.Program.Patch(String directory) в C:\Git\C#\Memoria\Memoria.Patcher\Program.cs:строка 107


  Устаревший мусор
Но после обработки получаю ошибку
[quote]"Member '{0}' is declared in another module and needs to be imported"
в Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
в Mono.Cecil.SignatureWriter.WriteTypeSignature(TypeReference type)
в Mono.Cecil.SignatureWriter.WriteGenericInstanceSignature(IGenericInstance instance)
в Mono.Cecil.MetadataBuilder.GetMethodSpecSignature(MethodSpecification method_spec)
в Mono.Cecil.MetadataBuilder.CreateMethodSpecRow(MethodSpecification method_spec)
в Mono.Cecil.MetadataBuilder.GetMethodSpecToken(MethodSpecification method_spec)
в Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
в Mono.Cecil.Cil.CodeWriter.WriteOperand(Instruction instruction)
в Mono.Cecil.Cil.CodeWriter.WriteInstructions()
в Mono.Cecil.Cil.CodeWriter.WriteResolvedMethodBody(MethodDefinition method)
в Mono.Cecil.Cil.CodeWriter.WriteMethodBody(MethodDefinition method)
в Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method)
в Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type)
в Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
в Mono.Cecil.MetadataBuilder.AddTypeDefs()
в Mono.Cecil.MetadataBuilder.BuildTypes()
в Mono.Cecil.MetadataBuilder.BuildModule()
в Mono.Cecil.ModuleWriter.<BuildMetadata>b__0(MetadataBuilder builder, MetadataReader _)
в Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
в Mono.Cecil.ModuleWriter.WriteModuleTo(ModuleDefinition module, Stream stream, WriterParameters parameters)
в Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
в Mono.Cecil.AssemblyDefinition.Write(String fileName)[/quote]

Проблема в том, что в процессе замены инструкций я добавил проверку после каждой:
MemberReference op = instructions[i].Operand as MemberReference;
if (op != null)
{
    if (op.Module != module)
        throw new InvalidCastException();
}


И я, честно говоря, не понимаю, по какой причине у меня эта проверка проходит нормально, а Mono падает — откуда он берёт этот проклятущий MemberReference с левым модулем?

Хотя это явно только начало — автор игноирует Generic'и, аттрибуты, исключения, но это можно будет дописать по мере возникновения проблем.

---
Ох, блин...
if (member == null || member.Module != this.module)
throw MetadataBuilder.CreateForeignMemberException(member);

Возможно, причина в том, что member == null

---
Тьфу, пропасть!
Точно. ldfld null
Буду разбираться — в какой момент (и где) я его потерял...
---
Ура! Прорвался.
НЕЛЬЗЯ удалять из сборки старый тип, до того, как все ссылки на него не будут заменены на новый.
Как и ожидалось, впилился в Generic'и, но это прогресс. Едем дальше!

   в Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
   в Mono.Cecil.SignatureWriter.WriteTypeSignature(TypeReference type)
   в Mono.Cecil.SignatureWriter.WriteGenericInstanceSignature(IGenericInstance instance)
   в Mono.Cecil.MetadataBuilder.GetMethodSpecSignature(MethodSpecification method_spec)
   в Mono.Cecil.MetadataBuilder.CreateMethodSpecRow(MethodSpecification method_spec)
   в Mono.Cecil.MetadataBuilder.GetMethodSpecToken(MethodSpecification method_spec)
   в Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
   в Mono.Cecil.Cil.CodeWriter.WriteOperand(Instruction instruction)
   в Mono.Cecil.Cil.CodeWriter.WriteInstructions()
   в Mono.Cecil.Cil.CodeWriter.WriteResolvedMethodBody(MethodDefinition method)
   в Mono.Cecil.Cil.CodeWriter.WriteMethodBody(MethodDefinition method)
   в Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method)
   в Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type)
   в Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
   в Mono.Cecil.MetadataBuilder.AddTypeDefs()
   в Mono.Cecil.MetadataBuilder.BuildTypes()
   в Mono.Cecil.MetadataBuilder.BuildModule()
   в Mono.Cecil.ModuleWriter.<BuildMetadata>b__0(MetadataBuilder builder, MetadataReader _)
   в Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
   в Mono.Cecil.ModuleWriter.WriteModuleTo(ModuleDefinition module, Stream stream, WriterParameters parameters)
   в Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
   в Mono.Cecil.AssemblyDefinition.Write(String fileName)