От: | Albeoris | ||
Дата: | 26.04.16 02:42 | ||
Оценка: | 66 (1) |
public sealed class TypeReplacer
{
private readonly String _fullName;
private readonly TypeReference _newReference;
private readonly TypeDefinition _newDefination;
private readonly List<ArrayType> _newArrayReferences;
private readonly Dictionary<TypeReference, TypeDefinition> _arrayDefinitions;
private ModuleDefinition _module;
private MethodDefinition _method;
public TypeReplacer(String fullName, TypeReference newReference)
{
_fullName = fullName;
_newReference = newReference;
_newDefination = newReference.Resolve();
_newArrayReferences = new List<ArrayType>();
_arrayDefinitions = new Dictionary<TypeReference, TypeDefinition>();
}
public void Replace(ModuleDefinition module)
{
_module = module;
foreach (TypeDefinition type in _module.Types)
ProcessType(type);
}
private void ProcessType(TypeDefinition type)
{
if (type.FullName == _fullName)
return;
ProcessProperties(type);
ProcessFields(type);
ProcessMethods(type);
ProcessNestedTypes(type);
}
private void ProcessNestedTypes(TypeDefinition type)
{
if (!type.HasNestedTypes)
return;
foreach (TypeDefinition nested in type.NestedTypes)
ProcessType(nested);
}
private void ProcessProperties(TypeDefinition type)
{
foreach (PropertyDefinition p in type.Properties)
{
TypeReference newType;
if (TryGetNewType(p.PropertyType, out newType))
p.PropertyType = newType;
}
}
private void ProcessFields(TypeDefinition type)
{
foreach (FieldDefinition f in type.Fields)
{
TypeReference newType;
if (TryGetNewType(f.FieldType, out newType))
f.FieldType = newType;
}
}
private void ProcessMethods(TypeDefinition type)
{
foreach (MethodDefinition m in type.Methods)
{
_method = m;
ProcessMethod();
}
}
private void ProcessMethod()
{
TypeReference newType;
if (TryGetNewType(_method.ReturnType, out newType))
_method.ReturnType = newType;
ProcessMethodParameters();
ProcessMethodBody();
}
private void ProcessMethodParameters()
{
if (!_method.HasParameters)
return;
foreach (ParameterDefinition p in _method.Parameters)
{
TypeReference newType;
if (TryGetNewType(p.ParameterType, out newType))
p.ParameterType = newType;
}
}
private void ProcessMethodBody()
{
if (!_method.HasBody)
return;
ProcessMethodBodyVariables();
ProcessMethodBodyInstructions();
}
private void ProcessMethodBodyVariables()
{
if (!_method.Body.HasVariables)
return;
foreach (VariableDefinition v in _method.Body.Variables)
{
TypeReference newType;
if (TryGetNewType(v.VariableType, out newType))
v.VariableType = newType;
}
}
private void ProcessMethodBodyInstructions()
{
TypeReference newType;
MethodBody body = _method.Body;
Collection<Instruction> instructions = body.Instructions;
for (int i = 0; i < instructions.Count; i++)
{
Instruction inst = instructions[i];
switch (inst.OpCode.OperandType)
{
case OperandType.InlineField:
case OperandType.InlineMethod:
case OperandType.InlineTok:
case OperandType.InlineType:
break;
default:
continue;
}
IGenericInstance genericInstance = inst.Operand as IGenericInstance;
if (genericInstance != null && genericInstance.HasGenericArguments)
{
for (int g = 0; g < genericInstance.GenericArguments.Count; g++)
{
if (TryGetNewType(genericInstance.GenericArguments[g], out newType))
genericInstance.GenericArguments[g] = newType;
}
}
TypeReference typeReference = inst.Operand as TypeReference;
if (typeReference != null)
{
if (TryGetNewType(typeReference, out newType))
instructions.Replace(i, RecreateTypeOperand(inst, newType));
continue;
}
MethodReference methodReference = inst.Operand as MethodReference;
if (methodReference != null)
{
if (TryGetNewType(methodReference.DeclaringType, out newType))
instructions.Replace(i, RecreateMethodOperand(inst, newType));
continue;
}
FieldReference fieldReference = inst.Operand as FieldReference;
if (fieldReference != null)
{
if (TryGetNewType(fieldReference.DeclaringType, out newType))
instructions.Replace(i, RecreateFieldOperand(inst, newType));
continue;
}
}
}
private Instruction RecreateMethodOperand(Instruction inst, TypeReference newType)
{
MethodDefinition method = ResolveType(newType).GetMethod((MethodReference)inst.Operand);
MethodReference methodReference = _module.Import(method);
return Instruction.Create(inst.OpCode, methodReference);
}
private Instruction RecreateFieldOperand(Instruction inst, TypeReference newType)
{
String oldName = ((FieldReference)inst.Operand).Name;
FieldDefinition field = ResolveType(newType).GetField(oldName);
FieldReference fieldReference = _module.Import(field);
return Instruction.Create(inst.OpCode, fieldReference);
}
private Instruction RecreateTypeOperand(Instruction inst, TypeReference newType)
{
return Instruction.Create(inst.OpCode, newType);
}
private Boolean TryGetNewType(TypeReference oldType, out TypeReference newType)
{
Int32 rank = 0;
while (oldType.IsArray)
{
rank++;
oldType = oldType.GetElementType();
}
if (oldType.FullName == _fullName)
{
newType = rank > 0 ? GetArrayType(rank) : _newReference;
return true;
}
GenericInstanceType genericType = oldType as GenericInstanceType;
if (genericType != null)
{
for (int index = 0; index < genericType.GenericArguments.Count; index++)
{
TypeReference argument = genericType.GenericArguments[index];
if (TryGetNewType(argument, out newType))
genericType.GenericArguments[index] = newType;
}
}
newType = null;
return false;
}
private TypeDefinition ResolveType(TypeReference type)
{
if (type == _newReference)
return _newDefination;
TypeDefinition definition;
if (!_arrayDefinitions.TryGetValue(type, out definition))
{
definition = type.Resolve();
_arrayDefinitions.Add(type, definition);
}
return definition;
}
private ArrayType GetArrayType(int rank)
{
for (int i = _newArrayReferences.Count; i <= rank; i++)
_newArrayReferences.Add(new ArrayType(_newReference, i + 1));
return _newArrayReferences[rank];
}
}
public static MethodDefinition GetMethod(this TypeDefinition td, MethodReference descriptor)
{
foreach (MethodDefinition method in td.Methods)
{
if (method.Name != descriptor.Name)
continue;
if (method.ReturnType.FullName != descriptor.ReturnType.FullName)
continue;
if (method.HasGenericParameters)
{
if (!descriptor.HasGenericParameters)
continue;
if (method.GenericParameters.Count != descriptor.GenericParameters.Count)
continue;
for (int i = 0; i < method.GenericParameters.Count; i++)
{
if (method.GenericParameters[i].FullName != descriptor.GenericParameters[i].FullName)
continue;
}
}
else if (descriptor.HasGenericParameters)
{
continue;
}
if (method.HasParameters)
{
if (!descriptor.HasParameters)
continue;
if (method.Parameters.Count != descriptor.Parameters.Count)
continue;
for (int i = 0; i < method.Parameters.Count; i++)
{
ParameterDefinition p1 = method.Parameters[i];
ParameterDefinition p2 = descriptor.Parameters[i];
if (p1.ParameterType.FullName != p2.ParameterType.FullName)
continue;
if (p1.Attributes != p2.Attributes)
continue;
}
}
else if (descriptor.HasParameters)
{
continue;
}
return method;
}
throw new InvalidOperationException("Sequence contains more than one matching element.");
}
От: | Albeoris | ||
Дата: | 14.05.16 13:01 | ||
Оценка: | 22 (1) |
От: | Sinix | ||
Дата: | 17.04.16 20:18 | ||
Оценка: | 2 (1) |
От: | Lexey | ||
Дата: | 26.04.16 11:09 | ||
Оценка: | 1 (1) |
A> public sealed class TypeReplaser
A>
От: | Albeoris | ||
Дата: | 25.04.16 19:57 | ||
Оценка: | +1 |
.class extern forwarder SomeNamespace.C
{
.assembly extern SecondAssembly
}
От: | Albeoris | ||
Дата: | 25.04.16 22:45 | ||
Оценка: | +1 |
oldAssembly.MainModule.ExportedTypes
new ExportedType("namespace", "typeName", newAssembly.MainModule, /*ссылка на новую сборку*/)
oldAssembly.MainModule.AssemblyReferences
От: | Albeoris | ||
Дата: | 15.04.16 23:00 | ||
Оценка: |
От: | Sinix | ||
Дата: | 17.04.16 14:07 | ||
Оценка: |
От: | Albeoris | ||
Дата: | 17.04.16 19:08 | ||
Оценка: |
От: | Albeoris | ||
Дата: | 25.04.16 23:52 | ||
Оценка: |
public static UIKeyTrigger Input
{
get
{
if ((UnityEngine.Object) PersistenSingleton<UIManager>.Instance.gameObject == (UnityEngine.Object) null)
return (UIKeyTrigger) null;
return PersistenSingleton<UIManager>.Instance.gameObject.GetComponent<UIKeyTrigger>();
}
}
[SecuritySafeCritical]
public unsafe T GetComponent<T>()
{
CastHelper<T> castHelper = new CastHelper<T>();
this.GetComponentFastPath(typeof (T), new IntPtr((void*) &castHelper.onePointerFurtherThanT));
return castHelper.t;
}
[WrapperlessIcall]
[MethodImpl(MethodImplOptions.InternalCall)]
internal void GetComponentFastPath(System.Type type, IntPtr oneFurtherThanResultValue);
От: | Albeoris | ||
Дата: | 26.04.16 01:36 | ||
Оценка: |
в 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] Проблема в том, что в процессе замены инструкций я добавил проверку после каждой:
И я, честно говоря, не понимаю, по какой причине у меня эта проверка проходит нормально, а Mono падает — откуда он берёт этот проклятущий MemberReference с левым модулем? Хотя это явно только начало — автор игноирует Generic'и, аттрибуты, исключения, но это можно будет дописать по мере возникновения проблем. --- Ох, блин... if (member == null || member.Module != this.module) throw MetadataBuilder.CreateForeignMemberException(member); Возможно, причина в том, что member == null --- Тьфу, пропасть! Точно. ldfld null Буду разбираться — в какой момент (и где) я его потерял... --- Ура! Прорвался. НЕЛЬЗЯ удалять из сборки старый тип, до того, как все ссылки на него не будут заменены на новый. Как и ожидалось, впилился в Generic'и, но это прогресс. Едем дальше!
| |
От: | Albeoris | ||
Дата: | 26.04.16 14:36 | ||
Оценка: |