protected override void Weave(WeavingContext context, InstructionWriter writer) { var loggerField = GetLoggerField(context, true); writer.EmitInstructionField(OpCodeNumber.Ldsfld, loggerField); writer.EmitInstructionMethod(OpCodeNumber.Call, GetLoggerMethod(context.Method.Module)); }
public void Weave(WeavingContext context, InstructionBlock block) { InstructionSequence nextSequence = null; InstructionSequence sequence = null; sequence = context.Method.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(sequence, NodePosition.Before, null); context.InstructionWriter.AttachInstructionSequence(sequence); context.InstructionWriter.EmitInstructionParameter(OpCodeNumber.Ldarg, this.paramDef); context.InstructionWriter.EmitInstructionType(OpCodeNumber.Box, this.paramDef.ParameterType); context.InstructionWriter.EmitInstruction(OpCodeNumber.Ldnull); context.InstructionWriter.EmitInstruction(OpCodeNumber.Ceq); nextSequence = context.Method.MethodBody.CreateInstructionSequence(); context.InstructionWriter.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, nextSequence); context.InstructionWriter.EmitInstructionString(OpCodeNumber.Ldstr, this.paramDef.Name); context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Newobj, context.Method.Module.FindMethod( typeof (ArgumentNullException).GetConstructor( new[] {typeof (string)}), BindingOptions.Default)); context.InstructionWriter.EmitInstruction(OpCodeNumber.Throw); context.InstructionWriter.DetachInstructionSequence(); block.AddInstructionSequence(nextSequence, NodePosition.After, sequence); sequence = nextSequence; context.InstructionWriter.AttachInstructionSequence(sequence); context.InstructionWriter.DetachInstructionSequence(); }
/// <summary> /// Weaves the specified context. /// </summary> /// <param name="context">The context.</param> /// <param name="block">The block.</param> public void Weave(WeavingContext context, InstructionBlock block) { LocalVariableSymbol parameters = block.DefineLocalVariable(context.Method.Module.FindType(typeof(ParameterDictionary), BindingOptions.Default), NameGenerator.Generate("parameters")); InstructionSequence entrySequence = context.Method.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(entrySequence, NodePosition.Before, null); InstructionWriter writer = context.InstructionWriter; writer.AttachInstructionSequence(entrySequence); writer.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden); writer.EmitInstructionMethod(OpCodeNumber.Call, context.Method.Module.FindMethod(typeof(InternalHelperMethods).GetMethod("CreateParameterCollection"), BindingOptions.Default)); IMethod add = context.Method.Module.FindMethod(typeof(ParameterDictionary).GetMethod("Add", new[] { typeof(string), typeof(object) }), BindingOptions.Default); short parameterIndex = context.Method.IsStatic ? (short)0 : (short)1; foreach (var parameter in method.Parameters) { writer.EmitInstruction(OpCodeNumber.Dup); writer.EmitInstructionString(OpCodeNumber.Ldstr, new LiteralString(parameter.Name)); writer.EmitInstructionInt16(OpCodeNumber.Ldarg, parameterIndex++); if (parameter.ParameterType.GetSystemType(null, null).IsValueType) { writer.EmitInstructionType(OpCodeNumber.Box, parameter.ParameterType); } writer.EmitInstructionMethod(OpCodeNumber.Callvirt, add); } writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, parameters); writer.DetachInstructionSequence(); }
private static MethodDefDeclaration FindOnPropertyChangedMethodFromContext(WeavingContext context) { MethodDefDeclaration onPropertyChangedMethod = null; TypeDefDeclaration currentType = context.Method.DeclaringType; do { onPropertyChangedMethod = FindOnPropertyChangedMethod(currentType); if (onPropertyChangedMethod == null) { currentType = GetTypeDeclarationOfBase(currentType); } } while (onPropertyChangedMethod == null && currentType != null); if (onPropertyChangedMethod == null) { throw new Exception("PropFu was unable to find a method marked with the OnPropertyChangedAttribute in this class' hierarchy: " + context.Method.DeclaringType.Name); } if (onPropertyChangedMethod.Parameters.Count != 1 || onPropertyChangedMethod.Parameters[0].ParameterType.GetSystemType(null, null) != typeof(string)) { throw new Exception("PropFu found a method marked with OnNotifyPropertyChanged with the incorrect signature. The method must take one string parameter only: " + context.Method.DeclaringType.Name + "::" + context.Method.Name ); } return onPropertyChangedMethod; }
public void Weave(WeavingContext context, InstructionBlock block) { InstructionSequence sequence = context.Method.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(sequence, NodePosition.After, null); InstructionWriter writer = context.InstructionWriter; writer.AttachInstructionSequence(sequence); context.InstructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, context.ReturnValueVariable); context.InstructionWriter.EmitInstructionType(OpCodeNumber.Box, context.ReturnValueVariable.LocalVariable.Type); context.InstructionWriter.EmitInstruction(OpCodeNumber.Ldnull); context.InstructionWriter.EmitInstruction(OpCodeNumber.Ceq); InstructionSequence nextSequence = context.Method.MethodBody.CreateInstructionSequence(); context.InstructionWriter.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, nextSequence); context.InstructionWriter.EmitInstructionString(OpCodeNumber.Ldstr, "return value is null"); context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Newobj, context.Method.Module.FindMethod( typeof (ArgumentNullException).GetConstructor(new[] { typeof ( string ) }), BindingOptions.Default)); context.InstructionWriter.EmitInstruction(OpCodeNumber.Throw); block.AddInstructionSequence(nextSequence, NodePosition.After, sequence); writer.DetachInstructionSequence(); }
private static FieldDefDeclaration GetNonGenericLoggerField(WeavingContext context, bool create) { var type = context.Method.DeclaringType; foreach(var currentField in type.Fields) { if(currentField.Name == loggerFieldName) { return currentField; } } if(create) { FieldDefDeclaration field = new FieldDefDeclaration(); field.Name = loggerFieldName; field.FieldType = type.Module.FindType(typeof(ILog), BindingOptions.Default); field.Attributes = FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.InitOnly; type.Fields.Add(field); return field; } else { return null; } }
public void Weave(WeavingContext context, InstructionBlock block) { InstructionWriter iw = context.InstructionWriter; iw.AttachInstructionSequence(block.AddInstructionSequence()); iw.EmitInstructionMethod(OpCodeNumber.Call, methodToCall); iw.DetachInstructionSequence(); ReplacedAtLeastOneCall = true; }
public void Weave(WeavingContext context, InstructionBlock block) { IMethod oldOperand = context.InstructionReader.CurrentInstruction.MethodOperand; InstructionSequence sequence = block.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(sequence); context.InstructionWriter.AttachInstructionSequence(sequence); context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Callvirt, oldOperand); context.InstructionWriter.DetachInstructionSequence(); }
void IAdvice.Weave(WeavingContext context, InstructionBlock block) { Console.WriteLine("Weave"); IMethod method = this.methods[context.JoinPoint.Instruction.OpCodeNumber]; InstructionSequence sequence = block.AddInstructionSequence(null, NodePosition.After, null); context.InstructionWriter.AttachInstructionSequence(sequence); context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Call, method); context.InstructionWriter.DetachInstructionSequence(); }
public void Weave(WeavingContext context, InstructionBlock block) { InstructionSequence sequence = null; sequence = context.Method.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(sequence, NodePosition.After, null); context.InstructionWriter.AttachInstructionSequence(sequence); context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Call, context.Method.Module.FindMethod(m_type.Methods.GetOneByName("get_Instance").GetReflectionWrapper(new Type[]{},new Type[]{}),BindingOptions.Default)); context.InstructionWriter.DetachInstructionSequence(); }
bool IAdvice.RequiresWeave(WeavingContext context) { ITypeSignature addressType = context.StackTypeStatus.GetAt(1); bool weave = context.Method.DeclaringType != this.wrapperType && this.methods.ContainsKey(context.JoinPoint.Instruction.OpCodeNumber) && !((PointerTypeSignature)addressType.GetNakedType()).IsManaged; Console.WriteLine("method={0}, instruction={1}, address={2}, weave={3}", context.Method, context.JoinPoint.Instruction, addressType, weave); return(weave); }
protected static IField GetLoggerField(WeavingContext context, bool create) { var field = GetNonGenericLoggerField(context, create); if (field != null && context.Method.DeclaringType.IsGenericDefinition) { return GenericHelper.GetFieldCanonicalGenericInstance(field); } else { return field; } }
private static LogAttribute GetLogAttribute(WeavingContext context) { var logAttributeType = context.Method.Module.FindType(typeof(LogAttribute), BindingOptions.Default); foreach (var attribute in context.Method.CustomAttributes) { if (logAttributeType.Equals(attribute.Constructor.DeclaringType)) { return (LogAttribute)attribute.ConstructRuntimeObject(); } } throw new InvalidOperationException("This should never happen!"); }
public void Weave(WeavingContext context, InstructionBlock block) { InstructionSequence entrySequence = context.Method.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(entrySequence, NodePosition.Before, null); InstructionWriter writer = context.InstructionWriter; writer.AttachInstructionSequence(entrySequence); writer.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden); Weave(context, writer); writer.DetachInstructionSequence(); }
public static bool ToIsNullable(this NullableValue nullableValue, WeavingContext weavingContext) { switch (nullableValue) { case NullableValue.Oblivious: case NullableValue.Annotated: return(true); case NullableValue.NotAnnotated: return(false); default: weavingContext.WriteError("Unexpected nullable argument value."); return(true); } }
public void Weave( WeavingContext context, InstructionBlock block ) { switch ( context.JoinPoint.JoinPointKind ) { case JoinPointKinds.BeforeMethodBody: this.WeaveEntry( context, block ); break; case JoinPointKinds.AfterMethodBodySuccess: this.WeaveExit( context, block ); break; default: throw new ArgumentException(string.Format( "Unexpected join point kind: {0}", context.JoinPoint.JoinPointKind ) ); } }
private static InstructionSequence EmitLevelTest(WeavingContext context, InstructionWriter writer, string logLevel) { var loggerField = GetLoggerField(context, true); writer.EmitInstructionField(OpCodeNumber.Ldsfld, loggerField); // If level is enabled var systemIsLevelEnabled = typeof(ILog).GetProperty("Is" + logLevel + "Enabled").GetGetMethod(); var isLevelEnabled = context.Method.Module.FindMethod(systemIsLevelEnabled, BindingOptions.Default); writer.EmitInstructionMethod(OpCodeNumber.Callvirt, isLevelEnabled); var branchTarget = context.Method.MethodBody.CreateInstructionSequence(); writer.CurrentInstructionSequence.ParentInstructionBlock.AddInstructionSequence(branchTarget, NodePosition.After, writer.CurrentInstructionSequence); writer.EmitBranchingInstruction(OpCodeNumber.Brfalse, branchTarget); return branchTarget; }
public override void Execute() { // Uncomment to attach debugger when msbuild task runs: // if (ModuleDefinition.Assembly.Name.Name == "TestAssembly") // Debugger.Launch(); var weavingContext = new WeavingContext(this); weavingContext.WriteInfo("Starting weaving context build."); weavingContext.Build(); weavingContext.WriteInfo($"Starting injection - CheckOutputs: {weavingContext.CheckOutputs}, CheckNonPublic: {weavingContext.CheckNonPublic}."); try { InjectThrowHelpers(weavingContext); } catch (Exception ex) { throw new RuntimeNullablesException("Error injecting throw helpers.", ex); } var moduleContext = weavingContext.ModuleContext; foreach (var typeContext in moduleContext.TypeContexts.Values) { foreach (var methodContext in typeContext.MethodContexts) { try { InjectMethodChecks(methodContext); } catch (Exception ex) { throw new RuntimeNullablesException($"Error injecting method '{methodContext.Method}' with null checks.", ex); } } } if (RemoveAttributeLibraryReference(ModuleDefinition.AssemblyReferences)) { weavingContext.WriteInfo("Reference to attribute library removed."); } else { weavingContext.WriteInfo("Reference to attribute library not found - references remain unchanged."); } weavingContext.WriteInfo("Injection complete."); }
public void Weave(WeavingContext context, InstructionBlock block) { InstructionSequence nextSequence = null; InstructionSequence sequence = null; sequence = context.Method.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(sequence, NodePosition.Before, null); context.InstructionWriter.AttachInstructionSequence(sequence); IMethod isNullOrEmpty = context.Method.Module.FindMethod(typeof (string).GetMethod("IsNullOrEmpty"), BindingOptions.Default); // Checks if not empty context.InstructionWriter.EmitInstructionParameter(OpCodeNumber.Ldarg, paramDef); context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Call, isNullOrEmpty); nextSequence = context.Method.MethodBody.CreateInstructionSequence(); context.InstructionWriter.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, nextSequence); context.InstructionWriter.EmitInstructionString(OpCodeNumber.Ldstr, "Parameter is null or empty."); context.InstructionWriter.EmitInstructionString(OpCodeNumber.Ldstr, this.paramDef.Name); context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Newobj, context.Method.Module.FindMethod( typeof (ArgumentException).GetConstructor(new[] { typeof ( string ), typeof ( string ) }), BindingOptions.Default)); context.InstructionWriter.EmitInstruction(OpCodeNumber.Throw); context.InstructionWriter.DetachInstructionSequence(); block.AddInstructionSequence(nextSequence, NodePosition.After, sequence); sequence = nextSequence; context.InstructionWriter.AttachInstructionSequence(sequence); context.InstructionWriter.DetachInstructionSequence(); }
public void Weave(WeavingContext context, InstructionBlock block) { IList<ParameterDeclaration> args = new List<ParameterDeclaration>(); foreach(ParameterDeclaration p in context.Method.Parameters) { foreach (CustomAttributeDeclaration c in p.CustomAttributes) { object obj = c.ConstructRuntimeObject(); if (obj is NonNullAttribute) { args.Add(p); } } } InstructionSequence nextSequence = null; InstructionSequence sequence = null; sequence = context.Method.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(sequence, NodePosition.Before, null); context.InstructionWriter.AttachInstructionSequence(sequence); foreach (ParameterDeclaration p in args) { context.InstructionWriter.EmitInstructionParameter(OpCodeNumber.Ldarg, p); context.InstructionWriter.EmitInstructionType(OpCodeNumber.Box, p.ParameterType); context.InstructionWriter.EmitInstruction(OpCodeNumber.Ldnull); context.InstructionWriter.EmitInstruction(OpCodeNumber.Ceq); nextSequence = context.Method.MethodBody.CreateInstructionSequence(); context.InstructionWriter.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, nextSequence); context.InstructionWriter.EmitInstructionString(OpCodeNumber.Ldstr, (LiteralString)p.Name); context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Newobj, context.Method.Module.FindMethod(typeof(ArgumentNullException).GetConstructor(new Type[] { typeof(string) }), BindingOptions.Default)); context.InstructionWriter.EmitInstruction(OpCodeNumber.Throw); context.InstructionWriter.DetachInstructionSequence(); block.AddInstructionSequence(nextSequence, NodePosition.After, sequence); sequence = nextSequence; context.InstructionWriter.AttachInstructionSequence(sequence); } context.InstructionWriter.DetachInstructionSequence(); }
public override void Execute() { if (Environment.GetEnvironmentVariable("NOBSERVABLE_DEBUG_ATTACH") == "1") { LogError($"Attach debugger to {Process.GetCurrentProcess().Id}"); while (!Debugger.IsAttached) { Thread.Sleep(1000); } } var context = new WeavingContext(TypeSystem, this, ModuleDefinition); foreach (var t in AllTypes(ModuleDefinition.Types)) { var observeAll = t.CustomAttributes.Any(ca => ca.AttributeType.AreEqual(context.ObservableAttributeReference)); foreach (var p in t.Properties) { var getter = p.GetMethod; var setter = p.SetMethod; if (getter == null || setter == null) { continue; } if (getter.IsStatic || setter.IsStatic) { continue; } if (observeAll || p.CustomAttributes.Any(ca => ca.AttributeType.AreEqual(context.ObservableAttributeReference))) { IlInjector.InstrumentProperty(context, p); } } if (context.BlazorHelperAsm != null && IsBlazorComponent(t)) { if (t.Interfaces.Any(iface => iface.InterfaceType.FullName == "NObservable.Blazor.IObserverComponent")) { IlInjector.InstrumentBlazorComponent(context, t); } } } }
protected override void Weave(WeavingContext context, InstructionWriter writer) { switch(context.JoinPoint.JoinPointKind) { case JoinPointKinds.BeforeMethodBody: WeaveBeforeMethodBody(context, writer); break; case JoinPointKinds.AfterMethodBodySuccess: WeaveAfterMethodBodySuccess(context, writer); break; case JoinPointKinds.AfterMethodBodyException: WeaveAfterMethodBodyException(context, writer); break; default: throw new ArgumentOutOfRangeException("context"); } }
protected override void Weave(WeavingContext context, InstructionWriter writer) { ITypeSignature declaringType = context.Method.DeclaringType; if (declaringType.IsGenericDefinition) { var canonicalType = GenericHelper.GetTypeCanonicalGenericInstance(declaringType.GetTypeDefinition(BindingOptions.RequireGenericDefinition)); var genericContext = canonicalType.GetGenericContext(GenericContextOptions.ResolveGenericParameterDefinitions); declaringType = canonicalType.MapGenericArguments(genericContext); } writer.EmitInstructionType(OpCodeNumber.Ldtoken, declaringType); var typeGetType = typeof(Type).GetMethod("GetTypeFromHandle"); writer.EmitInstructionMethod(OpCodeNumber.Call, context.Method.Module.FindMethod(typeGetType, BindingOptions.Default)); var getLogger = context.Method.Module.FindMethod(typeof(LogManager).GetMethod("GetLogger", new[] { typeof(Type) }), BindingOptions.Default); writer.EmitInstructionMethod(OpCodeNumber.Call, getLogger); var loggerField = GetLoggerField(context, false); writer.EmitInstructionField(OpCodeNumber.Stsfld, loggerField); }
public bool RequiresWeave(WeavingContext context) { return(true); }
public void Weave(WeavingContext context, InstructionBlock block) { throw new NotImplementedException(); }
/// <summary> /// Requireses the weave. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> public bool RequiresWeave(WeavingContext context) { return context.JoinPoint.JoinPointKind == JoinPointKinds.BeforeMethodBody; }
public static TypeDefinition?GetIteratorStateMachineType(this MethodDefinition method, WeavingContext weavingContext) { return(method.GetConstructorArgValue <TypeReference>("System.Runtime.CompilerServices.IteratorStateMachineAttribute", weavingContext)?.Resolve()); }
public bool RequiresWeave(WeavingContext context) { throw new NotImplementedException(); }
public void Weave(WeavingContext context, InstructionBlock block) { switch (context.JoinPoint.JoinPointKind) { case JoinPointKinds.AfterMethodBodyException: this.WeaveException(context, block); break; case JoinPointKinds.AfterMethodBodySuccess: this.WeaveSuccess(context, block); break; case JoinPointKinds.BeforeMethodBody: this.WeaveEnter(context, block); break; } }
/// <summary> /// Emits the MSIL that creates local variable and initializes it with array of objects representing the specified tokens. /// </summary> /// <param name="context">Context for the weaving.</param> /// <param name="block">Block where the code has to be injected.</param> /// <param name="nonStaticTokens">List of tokens that the object array is created for.</param> /// <returns>Local variable that stores the reference to the array.</returns> /// <exception cref="ArgumentNullException"><paramref name="context"/>, <paramref name="block"/> or <paramref name="nonStaticTokens"/> is <see langword="null"/>.</exception> /// <remarks> /// <para>Code emitted by this method makes no assumptions on the state of the evaluation stack /// and it leaves the stack unmodified.</para> /// </remarks> private LocalVariableSymbol EmitCreateFormatArgumentArray(WeavingContext context, InstructionBlock block, IList<IMessageToken> nonStaticTokens) { if (context == null) { throw new ArgumentNullException("context"); } if (block == null) { throw new ArgumentNullException("block"); } if (nonStaticTokens == null) { throw new ArgumentNullException("nonStaticTokens"); } InstructionWriter emitter = context.InstructionWriter; // Array that store arguments for the formatting. LocalVariableSymbol args = block.DefineLocalVariable(context.Method.Module.FindType(typeof(object[]), BindingOptions.Default), "~args~{0}"); // Create the array for storing agruments for formatting (contains only dyncamic tokens). emitter.EmitInstructionInt32(OpCodeNumber.Ldc_I4, nonStaticTokens.Count); emitter.EmitInstructionType(OpCodeNumber.Newarr, this.parent.ObjectType); // Save the array into the local variable because it will be used multiple times. emitter.EmitInstructionLocalVariable(OpCodeNumber.Stloc, args); // Fill the array with the data. for (int index = 0; index < nonStaticTokens.Count; index++) { // Array to store the data in. emitter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, args); // Position in the array to store the data at. emitter.EmitInstructionInt32(OpCodeNumber.Ldc_I4, index); // Let the token generate the IL that pushes the argument onto the stack. nonStaticTokens[index].Emit(context); // Finally: store the generated object into the array at the given position. emitter.EmitInstruction(OpCodeNumber.Stelem_Ref); } return args; }
public bool RequiresWeave(WeavingContext context) { return(context.InstructionReader.CurrentInstruction.OpCodeNumber == OpCodeNumber.Call); }
public void Emit(WeavingContext context) { if (context == null) { throw new ArgumentNullException("context"); } // Ensure that the there is any return value. if (context.ReturnValueVariable != null) { context.InstructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, context.ReturnValueVariable); context.WeavingHelper.ToObject(this.returnParameter.ParameterType, context.InstructionWriter); } else { context.InstructionWriter.EmitInstruction(OpCodeNumber.Ldnull); } }
private static void InjectAsyncIteratorStateMachineChecks(MethodDefinition method, TypeDefinition stateMachineType, WeavingContext weavingContext) { var bclReferences = weavingContext.BclReferences; var moduleReferences = weavingContext.ModuleReferences; if (!(GetMoveNextMethod(stateMachineType) is { } moveNextMethod)) { WriteSkipWarning("'MoveNext' method not found on state machine."); return; } var moveNextMethodBody = moveNextMethod.Body; var instructions = moveNextMethodBody.Instructions; if (!(GetSetResultMethodRef(instructions, out int index) is { } setResultMethodRef)) { WriteSkipWarning("'SetResult' method not found."); return; } if (instructions[index - 1].OpCode != OpCodes.Ldc_I4_1) { WriteSkipWarning("Unexpected state machine implementation - 'SetResult' method argument was not true."); return; } if (!(GetSetExceptionMethodRef(setResultMethodRef.DeclaringType, bclReferences) is { } setExceptionMethodRef)) { WriteSkipWarning("'SetException' method not found."); return; } if (!(GetFieldFromCurrentGetter(stateMachineType) is { } currentField)) { WriteSkipWarning("'Current' getter with field reference not found."); return; } moveNextMethodBody.SimplifyMacros(); // For reliability just in case codegen is different and branches into this section of instructions exists // Go back one instruction to keep the argument for SetResult together with the call var oldBlockStart = instructions[--index]; // Stack currently has the SetException/SetResult object on it instructions.Insert(index++, Instruction.Create(OpCodes.Ldarg_0)); instructions.Insert(index++, Instruction.Create(OpCodes.Ldfld, currentField)); ILHelpers.InsertGetValueRef(ref index, instructions, currentField.FieldType); const string message = "Async enumerator result nullability contract was broken."; ILHelpers.InsertThrowHelperCallIfValueRefIsNull( ref index, instructions, moduleReferences.GetAsyncResultNullExceptionMethod, message, oldBlockStart); instructions.Insert(index++, Instruction.Create(OpCodes.Call, setExceptionMethodRef)); instructions.Insert(index++, Instruction.Create(OpCodes.Ret)); moveNextMethodBody.SimplifyMacros(); void WriteSkipWarning(string message) => weavingContext.WriteWarning($"Skipping async iterator state machine result checks on method '{method}': {message}"); }
private static void InjectIteratorStateMachineChecks(MethodDefinition method, TypeDefinition stateMachineType, WeavingContext weavingContext) { var moduleReferences = weavingContext.ModuleReferences; if (!(GetMoveNextMethod(stateMachineType) is { } moveNextMethod)) { WriteSkipWarning("'MoveNext' method not found on state machine."); return; } if (!(GetFieldFromCurrentGetter(stateMachineType) is { } currentField)) { WriteSkipWarning("'Current' getter with field reference not found."); return; } var moveNextMethodBody = moveNextMethod.Body; var instructions = moveNextMethodBody.Instructions; moveNextMethodBody.SimplifyMacros(); for (int index = 1; index < instructions.Count; index++) { var instruction = instructions[index]; // Inject checks before all successful MoveNext operations. if (instruction.OpCode == OpCodes.Ret && instruction.Previous.OpCode == OpCodes.Ldc_I4 && (int)instruction.Previous.Operand == 1) { index--; instructions.Insert(index++, Instruction.Create(OpCodes.Ldarg_0)); instructions.Insert(index++, Instruction.Create(OpCodes.Ldfld, currentField)); ILHelpers.InsertGetValueRef(ref index, instructions, currentField.FieldType); const string message = "Enumerator result nullability contract was broken."; ILHelpers.InsertThrowHelperCallIfValueRefIsNull( ref index, instructions, moduleReferences.ThrowOutputNullMethod, message, instructions[index]); index += 2; } } moveNextMethodBody.OptimizeMacros(); void WriteSkipWarning(string message) => weavingContext.WriteWarning($"Skipping iterator state machine result checks on method '{method}': {message}"); }
private void WeaveSuccess(WeavingContext context, InstructionBlock block) { LogLevel level = this.attribute.ExitLevel; string text = this.attribute.ExitText; this.EmitCheckingAndTemplateLogging(context, block, level, text); }
private static void InjectAsyncStateMachineCheck(MethodDefinition method, TypeDefinition stateMachineType, WeavingContext weavingContext) { var bclReferences = weavingContext.BclReferences; var moduleReferences = weavingContext.ModuleReferences; if (!(GetMoveNextMethod(stateMachineType) is { } moveNextMethod)) { WriteSkipWarning("'MoveNext' method not found."); return; } var moveNextMethodBody = moveNextMethod.Body; var instructions = moveNextMethodBody.Instructions; if (!(GetSetResultMethodRef(instructions, out int index) is { } setResultMethodRef)) { WriteSkipWarning("'SetResult' method not found."); return; } if (!(GetSetExceptionMethodRef(setResultMethodRef.DeclaringType, bclReferences) is { } setExceptionMethodRef)) { WriteSkipWarning("'SetException' method not found."); return; } var resultType = ((GenericInstanceType)setResultMethodRef.DeclaringType).GenericArguments[0]; moveNextMethodBody.SimplifyMacros(); // For reliability just in case codegen is different and branches into this section of instructions exists // Keep instruction that loads result value where is it so that branches stay pointed to it but insert another one that stays with the SetResult call. var oldLoadResultInstruction = instructions[--index]; var newLoadResultInstruction = oldLoadResultInstruction.Clone(); instructions.Insert(++index, newLoadResultInstruction); // Don't increment index so this stays with the SetResult call // Value on stack is the result value ILHelpers.InsertGetValueRef(ref index, instructions, resultType); const string message = "Async task result nullability contract was broken."; ILHelpers.InsertThrowHelperCallIfValueRefIsNull( ref index, instructions, moduleReferences.GetAsyncResultNullExceptionMethod, message, newLoadResultInstruction); instructions.Insert(index++, Instruction.Create(OpCodes.Call, setExceptionMethodRef)); instructions.Insert(index++, Instruction.Create(OpCodes.Ret)); moveNextMethodBody.OptimizeMacros(); void WriteSkipWarning(string message) => weavingContext.WriteWarning($"Skipping async state machine result check on method '{method}': {message}"); }
public void Emit(WeavingContext context) { if (context == null) { throw new ArgumentNullException("context"); } context.InstructionWriter.EmitInstructionParameter(OpCodeNumber.Ldarg, this.parameter); context.InstructionWriter.EmitConvertToObject(this.parameter.ParameterType); }
private static bool InjectSynchronousTaskResultCheck(MethodDefinition method, ReturnBlockInfo returnBlockInfo, WeavingContext weavingContext) { var bclReferences = weavingContext.BclReferences; var moduleReferences = weavingContext.ModuleReferences; var taskType = (GenericInstanceType)method.ReturnType; var genericParameter = taskType.Resolve().GenericParameters[0]; var isCompletedGetter = new MethodReference("get_IsCompleted", bclReferences.BoolType, taskType) { HasThis = true }; var isCanceledGetter = new MethodReference("get_IsCanceled", bclReferences.BoolType, taskType) { HasThis = true }; var isFaultedGetter = new MethodReference("get_IsFaulted", bclReferences.BoolType, taskType) { HasThis = true }; var resultGetter = new MethodReference("get_Result", genericParameter, taskType) { HasThis = true }; if (isCompletedGetter.Resolve() == null) { WriteSkipWarning("'IsComplete' getter not found."); return(false); } if (isCanceledGetter.Resolve() == null) { WriteSkipWarning("'IsCanceled' getter not found."); return(false); } if (isFaultedGetter.Resolve() == null) { WriteSkipWarning("'IsFaulted' getter not found."); return(false); } if (resultGetter.Resolve() == null) { WriteSkipWarning("'Result' getter not found."); return(false); } var resultType = taskType.GenericArguments[0]; var instructions = method.Body.Instructions; var returnBlockStartPoints = returnBlockInfo.NewStartPoints; for (int i = 0; i < returnBlockStartPoints.Length; i++) { Instruction returnBlockStartPoint = returnBlockStartPoints[i]; int index = instructions.LastIndexOf(returnBlockStartPoint); // Value on stack is the return task var firstInstruction = Instruction.Create(OpCodes.Dup); instructions.Insert(index++, firstInstruction); instructions.Insert(index++, Instruction.Create(OpCodes.Call, isCompletedGetter)); instructions.Insert(index++, returnBlockInfo.CreateBranchInstruction(OpCodes.Brfalse_S, returnBlockStartPoint)); instructions.Insert(index++, Instruction.Create(OpCodes.Dup)); instructions.Insert(index++, Instruction.Create(OpCodes.Call, isCanceledGetter)); instructions.Insert(index++, returnBlockInfo.CreateBranchInstruction(OpCodes.Brtrue_S, returnBlockStartPoint)); instructions.Insert(index++, Instruction.Create(OpCodes.Dup)); instructions.Insert(index++, Instruction.Create(OpCodes.Call, isFaultedGetter)); instructions.Insert(index++, returnBlockInfo.CreateBranchInstruction(OpCodes.Brtrue_S, returnBlockStartPoint)); instructions.Insert(index++, Instruction.Create(OpCodes.Dup)); instructions.Insert(index++, Instruction.Create(OpCodes.Call, resultGetter)); ILHelpers.InsertGetValueRef(ref index, instructions, resultType); const string message = "Task result nullability contract was broken."; ILHelpers.InsertThrowHelperCallIfValueRefIsNull( ref index, instructions, moduleReferences.ThrowOutputNullMethod, message, returnBlockStartPoint, returnBlockInfo); returnBlockStartPoints[i] = firstInstruction; } return(true); void WriteSkipWarning(string message) => weavingContext.WriteWarning($"Skipping synchronous task result check on method '{method}': {message}"); }
public static bool?GetNullChecksAttributeValue(this ICustomAttributeProvider item, WeavingContext weavingContext, bool removeAttribute) { return(GetConstructorArgValue <bool?>(item, "RuntimeNullables.NullChecksAttribute", weavingContext, removeAttribute)); }
private static void InjectThrowHelpers(WeavingContext weavingContext) { var moduleContext = weavingContext.ModuleContext; var module = weavingContext.ModuleContext.Module; var bclReferences = weavingContext.BclReferences; var throwHelperType = moduleContext.Module.Types.FirstOrDefault(t => t.FullName == "RuntimeNullables.ThrowHelpers"); bool wasTypeInjected = false; if (throwHelperType == null) { throwHelperType = InjectThrowHelperType(); weavingContext.WriteInfo("Throw helper class not found - injecting standard throw helpers."); wasTypeInjected = true; } const string ThrowArgumentNullMethod = "ThrowArgumentNull"; if (!(GetThrowHelperMethod(ThrowArgumentNullMethod) is { } throwArgumentNullMethod)) { throwArgumentNullMethod = InjectThrowHelperMethod(ThrowArgumentNullMethod, "paramName", bclReferences.ArgumentNullExceptionConstructor); if (!wasTypeInjected) { weavingContext.WriteInfo("Argument null throw helper method not found on user class - injecting standard throw helper."); } } MethodDefinition throwOutputNullMethod = null; MethodDefinition getAsyncResultNullExceptionMethod = null; if (weavingContext.CheckOutputs) { const string ThrowOutputNullMethod = "ThrowOutputNull"; if ((throwOutputNullMethod = GetThrowHelperMethod(ThrowOutputNullMethod)) == null) { throwOutputNullMethod = InjectThrowHelperMethod(ThrowOutputNullMethod, "message", bclReferences.NullReferenceExceptionConstructor); if (!wasTypeInjected) { weavingContext.WriteInfo("Output null throw helper method not found on user class - injecting standard throw helper."); } } const string GetAsyncResultNullExceptionMethod = "GetAsyncResultNullException"; if ((getAsyncResultNullExceptionMethod = GetThrowHelperMethod(GetAsyncResultNullExceptionMethod)) == null) { getAsyncResultNullExceptionMethod = InjectThrowHelperMethod( GetAsyncResultNullExceptionMethod, "message", bclReferences.NullReferenceExceptionConstructor); if (!wasTypeInjected) { weavingContext.WriteInfo("Async result null throw helper method not found on user class - injecting standard throw helper."); } } } weavingContext.ModuleReferences = new ModuleReferences(throwArgumentNullMethod, throwOutputNullMethod, getAsyncResultNullExceptionMethod); MethodDefinition?GetThrowHelperMethod(string methodName) { var method = throwHelperType.Methods.FirstOrDefault(m => !m.HasGenericParameters && m.Name == methodName && m.Parameters.Count == 1 && m.Parameters[0].ParameterType.FullName == bclReferences.StringType.FullName); if (method != null) { if (!method.IsStatic) { throw new RuntimeNullablesException("Throw helper methods must be static."); } var returnType = DoesThrowHelperThrow(methodName) ? bclReferences.VoidType : bclReferences.ExceptionType; if (method.ReturnType.FullName != returnType.FullName) { throw new RuntimeNullablesException($"Throw helper method '{methodName}' must return '{returnType}'."); } } return(method); } MethodDefinition InjectThrowHelperMethod(string methodName, string stringParamName, MethodReference exceptionConstructor) { const MethodAttributes methodAttributes = MethodAttributes.Assembly | MethodAttributes.HideBySig | MethodAttributes.Static; bool throws = DoesThrowHelperThrow(methodName); var method = new MethodDefinition(methodName, methodAttributes, throws ? bclReferences.VoidType : bclReferences.ExceptionType); method.Parameters.Add(new ParameterDefinition(stringParamName, ParameterAttributes.None, bclReferences.StringType)); if (!wasTypeInjected) { AddGeneratedCodeAttribute(method); } var instructions = method.Body.Instructions; instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); instructions.Add(Instruction.Create(OpCodes.Newobj, exceptionConstructor)); instructions.Add(throws ? Instruction.Create(OpCodes.Throw) : Instruction.Create(OpCodes.Ret)); throwHelperType.Methods.Add(method); return(method); } TypeDefinition InjectThrowHelperType() { const TypeAttributes typeAttributes = TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit; var type = new TypeDefinition("RuntimeNullables", "ThrowHelpers", typeAttributes, bclReferences.ObjectType); AddGeneratedCodeAttribute(type); module.Types.Add(type); return(type); } void AddGeneratedCodeAttribute(ICustomAttributeProvider item) { // ("RuntimeNullables.Fody", "0.9.1") const string dataString = "01 00 15 52 75 6e 74 69 6d 65 4e 75 6c 6c 61 62 6c 65 73 2e 46 6f 64 79 05 30 2e 39 2e 31 00 00"; byte[] data = dataString.Split(' ').Select(b => byte.Parse(b, NumberStyles.HexNumber, null)).ToArray(); var attribute = new CustomAttribute(bclReferences.GeneratedCodeAttributeConstructor, data); item.CustomAttributes.Add(attribute); }
public static NullableValue?GetNullableAttributeValue(this ICustomAttributeProvider item, int itemOrdinal, WeavingContext weavingContext) { object argValue = GetConstructorArgValue <object>(item, "System.Runtime.CompilerServices.NullableAttribute", weavingContext); if (argValue == null) { return(null); } if (argValue is CustomAttributeArgument[] arrayValue) { argValue = arrayValue[Math.Min(arrayValue.Length - 1, itemOrdinal)].Value; } if (argValue is byte value) { return((NullableValue)value); } weavingContext.WriteError("Unexpected nullable attribute constructor argument type."); return(null); }
public void Weave(WeavingContext context, PostSharp.CodeModel.InstructionBlock block) { TypeDefDeclaration typeDef = m_type; // Declare the static field FieldDefDeclaration fieldDef = new FieldDefDeclaration(); fieldDef.Attributes = FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.NotSerialized | FieldAttributes.InitOnly; fieldDef.Name = "s_instance"; fieldDef.FieldType = typeDef; typeDef.Fields.Add(fieldDef); // Declare the static accessor. PropertyDeclaration propDef = new PropertyDeclaration(); propDef.Name = "Instance"; typeDef.Properties.Add(propDef); MethodSemanticDeclaration sematic = new MethodSemanticDeclaration(); sematic.Semantic = MethodSemantics.Getter; MethodDefDeclaration methodDef = new MethodDefDeclaration(); methodDef.Name = "get_Instance"; methodDef.Attributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static | MethodAttributes.SpecialName; methodDef.CallingConvention = CallingConvention.Default; typeDef.Methods.Add(methodDef); ParameterDeclaration retVal = new ParameterDeclaration(); retVal.ParameterType = typeDef; retVal.Attributes = ParameterAttributes.Retval; methodDef.ReturnParameter = retVal; sematic.Method = methodDef; propDef.Members.Add(sematic); propDef.PropertyType = typeDef; methodDef.MethodBody = new MethodBodyDeclaration(); methodDef.MethodBody.MaxStack = 1; methodDef.MethodBody.RootInstructionBlock = methodDef.MethodBody.CreateInstructionBlock(); //throw new NotFiniteNumberException(); InstructionSequence sequence = methodDef.MethodBody.CreateInstructionSequence(); methodDef.MethodBody.RootInstructionBlock.AddInstructionSequence(sequence, NodePosition.After , null); context.InstructionWriter.AttachInstructionSequence(sequence); context.InstructionWriter.EmitInstructionField(OpCodeNumber.Ldsfld, typeDef.Fields.GetByName("s_instance")); context.InstructionWriter.EmitInstruction(OpCodeNumber.Ret); context.InstructionWriter.DetachInstructionSequence(); // code for the static constructor sequence = context.Method.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(sequence, NodePosition.Before, null); context.InstructionWriter.AttachInstructionSequence(sequence); context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Newobj, typeDef.Methods.GetOneByName(".ctor")); context.InstructionWriter.EmitInstructionField(OpCodeNumber.Stsfld, typeDef.Fields.GetByName("s_instance")); context.InstructionWriter.DetachInstructionSequence(); // Change visibility to the constructor typeDef.Methods.GetOneByName(".ctor").Attributes = MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; }
public static NullableValue?GetNullableContextAttributeValue(this ICustomAttributeProvider item, WeavingContext weavingContext) { return((NullableValue?)GetConstructorArgValue <byte?>(item, "System.Runtime.CompilerServices.NullableContextAttribute", weavingContext)); }
/// <summary> /// Emits the MSIL which checks if the logging is enabled and logs the message. /// </summary> /// <param name="context">Weaving context.</param> /// <param name="block">Block where the code has to be injected.</param> /// <param name="level">Level for the message.</param> /// <param name="template">Template that will be tokenized in order to get message text.</param> /// <exception cref="ArgumentNullException"><paramref name="context"/>, <paramref name="block"/> or <paramref name="template"/> is <see langword="null"/>.</exception> /// <exception cref="FormatException">Template is not valid.</exception> /// <remarks> /// <para>If the <paramref name="level"/> is set to <see cref="LogLevel.None"/>, the method emits no code.</para> /// </remarks> private void EmitCheckingAndTemplateLogging(WeavingContext context, InstructionBlock block, LogLevel level, string template) { if (context == null) { throw new ArgumentNullException("context"); } if (block == null) { throw new ArgumentNullException("block"); } if (template == null) { throw new ArgumentNullException("template"); } if (level != LogLevel.None) { // Method being woven and the type the method is declared in. MethodDefDeclaration wovenMethod = context.Method; TypeDefDeclaration wovenType = wovenMethod.DeclaringType; // Objects that contain required methods, fields, etc. LogLevelSupportItem supportItem = this.parent.GetSupportItem(level); PerTypeLoggingData perTypeLoggingData = this.parent.GetPerTypeLoggingData(wovenType); // Get the tokens for the message template. StringBuilder messageFormatString = new StringBuilder(); List<IMessageToken> nonStaticTokens = new List<IMessageToken>(); List<IMessageToken> messageParts = TemplateParser.Tokenize(template, wovenMethod, attribute.IncludeParamName); MakeFormatString(messageParts, messageFormatString, nonStaticTokens); // Sequence that contains the logging check and the logging itself. InstructionSequence logEntrySequence = wovenMethod.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(logEntrySequence, NodePosition.Before, null); // Sequence that follows the logging code. InstructionSequence afterLoggingSequence = wovenMethod.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(afterLoggingSequence, NodePosition.After, logEntrySequence); // Check if logging is enabled and log the message. context.InstructionWriter.AttachInstructionSequence(logEntrySequence); context.InstructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden); EmitLoggingEnabledCheck(context.InstructionWriter, supportItem, perTypeLoggingData, afterLoggingSequence); if (nonStaticTokens.Count == 0) { // There are no dynamic tokens, use the faster logging method. EmitLogString(context.InstructionWriter, perTypeLoggingData.Log, supportItem.LogStringMethod, messageFormatString.ToString()); } else { // There are dynamic tokens, prepare log message at run-time. LocalVariableSymbol args = this.EmitCreateFormatArgumentArray(context, block, nonStaticTokens); EmitLogProviderStringArgs(context.InstructionWriter, perTypeLoggingData.Log, supportItem.LogCultureStringArgsMethod, this.parent.InvariantCultureGetter, messageFormatString.ToString(), args); } context.InstructionWriter.DetachInstructionSequence(); // Logging is finished (or skipped), do nothing. context.InstructionWriter.AttachInstructionSequence(afterLoggingSequence); context.InstructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden); context.InstructionWriter.EmitInstruction(OpCodeNumber.Nop); context.InstructionWriter.DetachInstructionSequence(); } }
public static T GetConstructorArgValue <T>(this ICustomAttributeProvider item, string attributeFullName, WeavingContext weavingContext, bool removeAttribute = false) { var attribute = item.CustomAttributes.SingleOrDefault(a => a.AttributeType.FullName == attributeFullName); if (attribute == null) { return(default);
private void WeaveException(WeavingContext context, InstructionBlock block) { LogLevel level = this.attribute.ExceptionLevel; string text = this.attribute.ExceptionText; // Inject the logging code only if the logging is turned on. if (this.attribute.ExceptionLevel != LogLevel.None) { // Method being woven and the type the method is declared in. MethodDefDeclaration wovenMethod = context.Method; TypeDefDeclaration wovenType = wovenMethod.DeclaringType; // Objects that contain required methods, fields, etc. LogLevelSupportItem supportItem = this.parent.GetSupportItem(level); PerTypeLoggingData perTypeLoggingData = this.parent.GetPerTypeLoggingData(wovenType); // Get the tokens for the message template. StringBuilder messageFormatString = new StringBuilder(); List<IMessageToken> nonStaticTokens = new List<IMessageToken>(); List<IMessageToken> messageParts = TemplateParser.Tokenize(text, wovenMethod, attribute.IncludeParamName); MakeFormatString(messageParts, messageFormatString, nonStaticTokens); // As log4net does not provide an overload for the LogXXX() methods which would accept // both exception and array of arguments for a format string, disallow usage of dynamic // tokens in the template. if (nonStaticTokens.Count > 0) { throw new FormatException("Message for logging exception can contain only placeholders whose value can be expanded at weaving time."); } // Variable that stores the reference to the thrown exception. LocalVariableSymbol exception = block.DefineLocalVariable(context.Method.Module.FindType(typeof(Exception), BindingOptions.Default), "~ex~{0}"); // Sequence that contains code that checks if the logging is enabled and logs the message. InstructionSequence logExceptionSequence = context.Method.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(logExceptionSequence, NodePosition.Before, null); // Sequence that contains code that is executed after logging. InstructionSequence afterLoggingSequence = context.Method.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(afterLoggingSequence, NodePosition.After, logExceptionSequence); // Emit code that checks if the logging is enabled and logs the message. context.InstructionWriter.AttachInstructionSequence(logExceptionSequence); context.InstructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden); context.InstructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Stloc_S, exception); EmitLoggingEnabledCheck(context.InstructionWriter, supportItem, perTypeLoggingData, afterLoggingSequence); EmitLogStringException(context.InstructionWriter, perTypeLoggingData.Log, supportItem.LogStringExceptionMethod, messageFormatString.ToString(), exception); context.InstructionWriter.DetachInstructionSequence(); // After logging is finished (or skipped), rethrow the exception. context.InstructionWriter.AttachInstructionSequence(afterLoggingSequence); context.InstructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden); context.InstructionWriter.EmitInstruction(OpCodeNumber.Rethrow); context.InstructionWriter.DetachInstructionSequence(); } else { // Logging is turned off, just rethrow the exception. InstructionSequence rethrowSequence = context.Method.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(rethrowSequence, NodePosition.Before, null); context.InstructionWriter.AttachInstructionSequence(rethrowSequence); context.InstructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden); context.InstructionWriter.EmitInstruction(OpCodeNumber.Rethrow); context.InstructionWriter.DetachInstructionSequence(); } }
public void Emit(WeavingContext context) { if (context == null) { throw new ArgumentNullException("context"); } context.InstructionWriter.EmitInstructionString(OpCodeNumber.Ldstr, this.Text); }
public bool RequiresWeave(WeavingContext context) { return true; }
private static void WeaveAfterMethodBodyException(WeavingContext context, InstructionWriter writer) { var attribute = GetLogAttribute(context); if (attribute.ExceptionLevel != LogLevel.None) { string logLevel = attribute.ExceptionLevel.ToString(); var branchTarget = EmitLevelTest(context, writer, logLevel); // Exception writer.EmitInstruction(OpCodeNumber.Dup); // Method name writer.EmitInstructionString(OpCodeNumber.Ldstr, GetMetodFullName(context)); // Message if (attribute.EntryMessage != null) { writer.EmitInstructionString(OpCodeNumber.Ldstr, attribute.ExceptionMessage); } else { writer.EmitInstruction(OpCodeNumber.Ldnull); } // Logger writer.EmitInstructionField(OpCodeNumber.Ldsfld, GetLoggerField(context, true)); // Call var systemExceptionLevel = loggerAttributeHelperType.GetMethod("Exception" + logLevel, BindingFlags.Static | BindingFlags.Public); Debug.Assert(systemExceptionLevel != null); var exceptionLevel = context.Method.Module.FindMethod(systemExceptionLevel, BindingOptions.Default); writer.EmitInstructionMethod(OpCodeNumber.Call, exceptionLevel); // throw writer.DetachInstructionSequence(); writer.AttachInstructionSequence(branchTarget); writer.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden); writer.EmitInstruction(OpCodeNumber.Rethrow); } }