コード例 #1
0
        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));
        }
コード例 #2
0
        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();
        }
コード例 #3
0
        /// <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();
        }
コード例 #4
0
        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;
        }
コード例 #5
0
        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();
        }
コード例 #6
0
        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;
            }
        }
コード例 #7
0
        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();
        }
コード例 #10
0
        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);
        }
コード例 #12
0
 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;
     }
 }
コード例 #13
0
 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!");
 }
コード例 #14
0
        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();
        }
コード例 #15
0
        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);
            }
        }
コード例 #16
0
        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 ) );
            }
        }
コード例 #17
0
        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;
        }
コード例 #18
0
        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.");
        }
コード例 #19
0
        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();
        }
コード例 #20
0
        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();
        }
コード例 #21
0
ファイル: ModuleWeaver.cs プロジェクト: n9/NObservable
    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);
                }
            }
        }
    }
コード例 #22
0
        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");
            }
        }
コード例 #23
0
        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);
        }
コード例 #24
0
 public bool RequiresWeave(WeavingContext context)
 {
     return(true);
 }
コード例 #25
0
 public void Weave(WeavingContext context, InstructionBlock block)
 {
     throw new NotImplementedException();
 }
コード例 #26
0
 /// <summary>
 /// Requireses the weave.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <returns></returns>
 public bool RequiresWeave(WeavingContext context)
 {
     return context.JoinPoint.JoinPointKind == JoinPointKinds.BeforeMethodBody;
 }
コード例 #27
0
 public static TypeDefinition?GetIteratorStateMachineType(this MethodDefinition method, WeavingContext weavingContext)
 {
     return(method.GetConstructorArgValue <TypeReference>("System.Runtime.CompilerServices.IteratorStateMachineAttribute", weavingContext)?.Resolve());
 }
コード例 #28
0
 public bool RequiresWeave(WeavingContext context)
 {
     throw new NotImplementedException();
 }
コード例 #29
0
 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;
       }
 }
コード例 #30
0
        /// <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);
 }
コード例 #32
0
        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);
            }
        }
コード例 #33
0
        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}");
        }
コード例 #34
0
        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}");
        }
コード例 #35
0
        private void WeaveSuccess(WeavingContext context, InstructionBlock block)
        {
            LogLevel level = this.attribute.ExitLevel;
              string text = this.attribute.ExitText;

              this.EmitCheckingAndTemplateLogging(context, block, level, text);
        }
コード例 #36
0
        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}");
        }
コード例 #37
0
        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);
        }
コード例 #38
0
        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}");
        }
コード例 #39
0
 public static bool?GetNullChecksAttributeValue(this ICustomAttributeProvider item, WeavingContext weavingContext, bool removeAttribute)
 {
     return(GetConstructorArgValue <bool?>(item, "RuntimeNullables.NullChecksAttribute", weavingContext, removeAttribute));
 }
コード例 #40
0
        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);
            }
コード例 #41
0
        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);
        }
コード例 #42
0
        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;
        }
コード例 #43
0
 public static NullableValue?GetNullableContextAttributeValue(this ICustomAttributeProvider item, WeavingContext weavingContext)
 {
     return((NullableValue?)GetConstructorArgValue <byte?>(item, "System.Runtime.CompilerServices.NullableContextAttribute", weavingContext));
 }
コード例 #44
0
        /// <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();
              }
        }
コード例 #45
0
        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);
コード例 #46
0
        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();
              }
        }
コード例 #47
0
        public void Emit(WeavingContext context)
        {
            if (context == null)
              {
            throw new ArgumentNullException("context");
              }

              context.InstructionWriter.EmitInstructionString(OpCodeNumber.Ldstr, this.Text);
        }
コード例 #48
0
 public bool RequiresWeave(WeavingContext context)
 {
     return true;
 }
コード例 #49
0
        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);
            }
        }