public static Missing_member_in_attribute ( string kind, |
||
kind | string | |
memberRef | ||
identifier | string | |
Результат |
private void SpecializeMembers <T>(SimpleTypeLookup <MemberAction <T> > lookup, AssemblyDefinition toTargetAssembly) where T : MemberReference, IMemberDefinition { foreach (var item in lookup[typeof(ModifiesMemberAttribute), typeof(MemberAliasAttribute)]) { item.TargetMember = GetPatchedMember(item.TypeAction.TargetType, item.YourMember, item.ActionAttribute); if (item.TargetMember == null) { var memberName = GetPatchedMemberName(item.YourMember, item.ActionAttribute); throw Errors.Missing_member_in_attribute(DisplayNameHelper.CommonNameForMemberDef <T>(), item.YourMember, memberName); } } }
private MethodDefinition GetBodySource(TypeDefinition targetType, MethodDefinition yourMethod, DuplicatesBodyAttribute insertAttribute) { //Note that the source type is resolved using yourMethod's module, which uses a different IMetadataResolver, //and thus will resolve the method from the target, unmodified assembly. var importSourceType = insertAttribute.SourceType != null ? yourMethod.Module.Import((TypeReference)insertAttribute.SourceType) : yourMethod.Module.Import(targetType); var importMethod = importSourceType.Resolve().GetMethodLike(yourMethod, insertAttribute.MethodName); var others = importSourceType.Resolve().Methods.Where(x => x.Name == insertAttribute.MethodName).ToArray(); if (importMethod == null) { throw Errors.Missing_member_in_attribute("method", yourMethod, insertAttribute.MethodName); } return(importMethod); }
/// <summary> /// Transfers the method body of yourMethod into the targetMethod, keeping everything neat and tidy, creating new copies of yourMethod's instructions. /// </summary> /// <param name="targetMethod">The target method.</param> /// <param name="yourMethod">Your instructions.</param> private void TransferMethodBody(MethodDefinition targetMethod, MethodDefinition yourMethod) { //TODO: This method needs to be refactored somehow. In particular, the IL transformation in PatchworkDebugRegisterAttribute needs to be applied separately. targetMethod.Body.Instructions.Clear(); var injectManual = yourMethod.GetCustomAttribute <PatchworkDebugRegisterAttribute>(); FieldReference debugFieldRef = null; _concat = _concat ?? targetMethod.Module.GetMethodLike(() => String.Concat("", "")); var instructionEquiv = new Dictionary <Instruction, Instruction>(); targetMethod.Body.InitLocals = yourMethod.Body.Variables.Count > 0; targetMethod.Body.Variables.Clear(); foreach (var yourVar in yourMethod.Body.Variables) { var targetVarType = FixTypeReference(yourVar.VariableType); var targetVar = new VariableDefinition(yourVar.Name, targetVarType); targetMethod.Body.Variables.Add(targetVar); } var ilProcesser = targetMethod.Body.GetILProcessor(); if (injectManual != null) { var debugDeclType = (TypeReference)injectManual.DeclaringType ?? targetMethod.DeclaringType; var debugMember = injectManual.DebugFieldName; debugFieldRef = debugDeclType.Resolve().GetField(debugMember); if (debugFieldRef == null) { throw Errors.Missing_member_in_attribute("field", yourMethod, debugMember); } ilProcesser.Emit(OpCodes.Ldstr, ""); ilProcesser.Emit(OpCodes.Stsfld, debugFieldRef); } //branch instructions reference other instructions in the method body as branch targets. //in order to fix them, I will first have to reconstruct the other instructions in the body for (int i = 0; i < yourMethod.Body.Instructions.Count; i++) { var yourInstruction = yourMethod.Body.Instructions[i]; var yourOperand = yourInstruction.Operand; //Note that properties or events are pure non-functional metadata, kind of like attributes. //They will never be directly referenced in a CIL instruction, though reflection is a different story of course. object targetOperand; OpCode targetOpcode = yourInstruction.OpCode; if (yourOperand is MethodReference) { var yourMethodOperand = (MethodReference)yourOperand; var memberAliasAttr = yourMethodOperand.Resolve().GetCustomAttribute <MemberAliasAttribute>(); if (memberAliasAttr != null && targetOpcode.EqualsAny(OpCodes.Call, OpCodes.Callvirt)) { switch (memberAliasAttr.CallMode) { case AliasCallMode.NonVirtual: targetOpcode = OpCodes.Call; break; case AliasCallMode.Virtual: targetOpcode = OpCodes.Callvirt; break; } } //FixMethodReference also resolves the aliased method, so processing MemberAliasAttribute isn't done yet. var targetMethodRef = FixMethodReference(yourMethodOperand); targetOperand = targetMethodRef; } else if (yourOperand is TypeReference) { //includes references to type parameters var yourTypeRef = (TypeReference)yourOperand; targetOperand = FixTypeReference(yourTypeRef); } else if (yourOperand is FieldReference) { var yourFieldRef = (FieldReference)yourOperand; targetOperand = FixFieldReference(yourFieldRef); } else if (yourOperand is ParameterReference) { var yourParamRef = (ParameterReference)yourOperand; targetOperand = FixParamReference(targetMethod, yourParamRef); } else { targetOperand = yourOperand; } var targetInstruction = Hacks.CreateInstruction(yourInstruction.OpCode, targetOperand); targetInstruction.OpCode = targetOpcode; targetInstruction.Operand = targetOperand; targetInstruction.SequencePoint = yourInstruction.SequencePoint; if (injectManual != null) { targetInstruction.OpCode = SimplifyOpCode(targetInstruction.OpCode); } var lastInstr = ilProcesser.Body.Instructions.LastOrDefault(); if (yourInstruction.SequencePoint != null && injectManual != null && (lastInstr == null || !IsBreakingOpCode(lastInstr.OpCode))) { var str = i == 0 ? "" : " ⇒ "; str += yourInstruction.SequencePoint.StartLine; ilProcesser.Emit(OpCodes.Ldsfld, debugFieldRef); ilProcesser.Emit(OpCodes.Ldstr, str); ilProcesser.Emit(OpCodes.Call, _concat); ilProcesser.Emit(OpCodes.Stsfld, debugFieldRef); } instructionEquiv[yourInstruction] = targetInstruction; ilProcesser.Append(targetInstruction); } targetMethod.Body.ExceptionHandlers.Clear(); if (yourMethod.Body.HasExceptionHandlers) { var handlers = from exhandler in yourMethod.Body.ExceptionHandlers select new ExceptionHandler(exhandler.HandlerType) { CatchType = exhandler.CatchType == null ? null : FixTypeReference(exhandler.CatchType), HandlerStart = instructionEquiv[exhandler.HandlerStart], HandlerEnd = instructionEquiv[exhandler.HandlerEnd], TryStart = instructionEquiv[exhandler.TryStart], TryEnd = instructionEquiv[exhandler.TryEnd], FilterStart = exhandler.FilterStart == null ? null : instructionEquiv[exhandler.FilterStart] }; foreach (var exhandlr in handlers) { targetMethod.Body.ExceptionHandlers.Add(exhandlr); } } foreach (var targetInstruction in ilProcesser.Body.Instructions) { var targetOperand = targetInstruction.Operand; if (targetOperand is Instruction) { //conditional branch instructions var asInstr = (Instruction)targetOperand; targetOperand = instructionEquiv[asInstr]; } else if (targetOperand is Instruction[]) { //Switch instruction (jump table) var asInstrs = ((Instruction[])targetOperand); var equivTargetInstrs = asInstrs.Select(instr => instructionEquiv[instr]).ToArray(); targetOperand = equivTargetInstrs; } targetInstruction.Operand = targetOperand; } }