Ejemplo n.º 1
0
 /// <summary>
 /// Emits the code needed to properly push an object on the stack,
 /// serializing the value if necessary.
 /// </summary>
 /// <param name="typeBuilder">The TypeBuilder for the method being built.</param>
 /// <param name="methodBuilder">The method currently being built.</param>
 /// <param name="invocationContext">The invocation context for this call.</param>
 /// <param name="invocationContexts">A list of invocation contexts that will be appended to.</param>
 /// <param name="invocationContextsField">The static field containing the array of invocation contexts at runtime.</param>
 /// <param name="parameterMapping">The mapping of source parameters to destination parameters.</param>
 /// <param name="serializationProvider">The serialization provider for the current interface.</param>
 /// <param name="serializationProviderField">
 /// The field on the current object that contains the serialization provider at runtime.
 /// This method assume the current object is stored in arg.0.
 /// </param>
 internal static void EmitSerializeValue(
     TypeBuilder typeBuilder,
     MethodBuilder methodBuilder,
     InvocationContext invocationContext,
     List <InvocationContext> invocationContexts,
     FieldBuilder invocationContextsField,
     ParameterMapping parameterMapping,
     TraceSerializationProvider serializationProvider,
     FieldBuilder serializationProviderField,
     List <(string, LambdaExpression)> parameterConverters)
Ejemplo n.º 2
0
        /// <summary>
        /// Emits the code needed to properly push an object on the stack,
        /// serializing the value if necessary.
        /// </summary>
        /// <param name="typeBuilder">The TypeBuilder for the method being built.</param>
        /// <param name="methodBuilder">The method currently being built.</param>
        /// <param name="invocationContext">The invocation context for this call.</param>
        /// <param name="invocationContexts">A list of invocation contexts that will be appended to.</param>
        /// <param name="invocationContextsField">The static field containing the array of invocation contexts at runtime.</param>
        /// <param name="i">The index of the current parameter being pushed.</param>
        /// <param name="sourceType">The type that the parameter is being converted from.</param>
        /// <param name="targetType">The type that the parameter is being converted to.</param>
        /// <param name="converter">An optional converter to apply to the source type.</param>
        /// <param name="serializationProvider">The serialization provider for the current interface.</param>
        /// <param name="serializationProviderField">
        /// The field on the current object that contains the serialization provider at runtime.
        /// This method assume the current object is stored in arg.0.
        /// </param>
        internal static void EmitSerializeValue(
			TypeBuilder typeBuilder,
			MethodBuilder methodBuilder,
			InvocationContext invocationContext,
			List<InvocationContext> invocationContexts,
			FieldBuilder invocationContextsField,
			int i,
			Type sourceType,
			Type targetType,
			LambdaExpression converter,
			TraceSerializationProvider serializationProvider,
			FieldBuilder serializationProviderField)
        {
            ILGenerator mIL = methodBuilder.GetILGenerator();

            // if the source is a parameter, then load the parameter onto the stack
            if (i >= 0)
                mIL.Emit(OpCodes.Ldarg, i + 1);

            // if a converter is passed in, then define a static method and use it to convert
            if (converter != null)
            {
                MethodBuilder mb = typeBuilder.DefineMethod(Guid.NewGuid().ToString(), MethodAttributes.Static | MethodAttributes.Public, converter.ReturnType, converter.Parameters.Select(p => p.Type).ToArray());
                converter.CompileToMethod(mb);
                mIL.Emit(OpCodes.Call, mb);

                // the object on the stack is now the return type. we may need to convert it further
                sourceType = converter.ReturnType;
            }

            // if the source type is a reference to the target type, we have to dereference it
            if (sourceType.IsByRef && sourceType.GetElementType() == targetType)
            {
                sourceType = sourceType.GetElementType();
                mIL.Emit(OpCodes.Ldobj, sourceType);
                return;
            }

            // if the types match, just put the argument on the stack
            if (sourceType == targetType)
                return;

            // this is not a match, so convert using the serializer.
            // verify that the target type is a string
            if (targetType != typeof(string))
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot convert type {0} to a type compatible with EventSource", targetType.FullName));

            // for fundamental types, just convert them with ToString and be done with it
            var underlyingType = Nullable.GetUnderlyingType(sourceType) ?? sourceType;
            if (!sourceType.IsGenericParameter && (underlyingType.IsEnum || (underlyingType.IsValueType && underlyingType.Assembly == typeof(string).Assembly)))
            {
                // convert the argument to a string with ToString
                LocalBuilder lb = mIL.DeclareLocal(sourceType);
                mIL.Emit(OpCodes.Stloc, lb.LocalIndex);
                mIL.Emit(OpCodes.Ldloca, lb.LocalIndex);
                mIL.Emit(OpCodes.Call, sourceType.GetMethod("ToString", Type.EmptyTypes));
                return;
            }

            // non-fundamental types use the object serializer
            var context = new TraceSerializationContext(invocationContext, i);
            context.EventLevel = serializationProvider.GetEventLevelForContext(context);
            if (context.EventLevel != null)
            {
                LocalBuilder lb = mIL.DeclareLocal(sourceType);
                mIL.Emit(OpCodes.Stloc, lb.LocalIndex);

                // get the object serializer from the this pointer
                mIL.Emit(OpCodes.Ldsfld, serializationProviderField);
                mIL.Emit(OpCodes.Ldloc, lb.LocalIndex);

                // if the source type is a reference to the target type, we have to dereference it
                if (sourceType.IsByRef)
                {
                    sourceType = sourceType.GetElementType();
                    mIL.Emit(OpCodes.Ldobj, sourceType);
                }

                // if it's a value type, we have to box it to log it
                if (sourceType.IsGenericParameter || sourceType.IsValueType)
                    mIL.Emit(OpCodes.Box, sourceType);

                // get the invocation context from the array on the provider
                mIL.Emit(OpCodes.Ldsfld, invocationContextsField);
                mIL.Emit(OpCodes.Ldc_I4, invocationContexts.Count);
                mIL.Emit(OpCodes.Ldelem, typeof(TraceSerializationContext));
                invocationContexts.Add(context);

                mIL.Emit(OpCodes.Callvirt, typeof(TraceSerializationProvider).GetMethod("ProvideSerialization", BindingFlags.Instance | BindingFlags.Public));
            }
            else
            {
                mIL.Emit(OpCodes.Pop);
                mIL.Emit(OpCodes.Ldnull);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Emits the code needed to properly push an object on the stack,
        /// serializing the value if necessary.
        /// </summary>
        /// <param name="typeBuilder">The TypeBuilder for the method being built.</param>
        /// <param name="methodBuilder">The method currently being built.</param>
        /// <param name="invocationContext">The invocation context for this call.</param>
        /// <param name="invocationContexts">A list of invocation contexts that will be appended to.</param>
        /// <param name="invocationContextsField">The static field containing the array of invocation contexts at runtime.</param>
        /// <param name="parameterMapping">The mapping of source parameters to destination parameters.</param>
        /// <param name="serializationProvider">The serialization provider for the current interface.</param>
        /// <param name="serializationProviderField">
        /// The field on the current object that contains the serialization provider at runtime.
        /// This method assume the current object is stored in arg.0.
        /// </param>
        internal static void EmitSerializeValue(
			TypeBuilder typeBuilder,
			MethodBuilder methodBuilder,
			InvocationContext invocationContext,
			List<InvocationContext> invocationContexts,
			FieldBuilder invocationContextsField,
			ParameterMapping parameterMapping,
			TraceSerializationProvider serializationProvider,
			FieldBuilder serializationProviderField)
        {
            var sourceCount = parameterMapping.Sources.Count();
            if (sourceCount == 0)
                return;

            if (sourceCount == 1)
            {
                var parameter = parameterMapping.Sources.First();

                EmitSerializeValue(
                    typeBuilder,
                    methodBuilder,
                    invocationContext,
                    invocationContexts,
                    invocationContextsField,
                    parameter.Position,
                    parameter.SourceType,
                    parameterMapping.CleanTargetType,
                    parameter.Converter,
                    serializationProvider,
                    serializationProviderField);
                return;
            }

            var il = methodBuilder.GetILGenerator();

            // use the serializer to serialize the objects
            var context = new TraceSerializationContext(invocationContext.SpecifyType(InvocationContextTypes.BundleParameters), -1);
            context.EventLevel = serializationProvider.GetEventLevelForContext(context);

            if (context.EventLevel != null)
            {
                // get the object serializer from the this pointer
                il.Emit(OpCodes.Ldsfld, serializationProviderField);

                // create a new dictionary strings and values
                il.Emit(OpCodes.Newobj, typeof(Dictionary<string, string>).GetConstructor(Type.EmptyTypes));

                foreach (var parameter in parameterMapping.Sources)
                {
                    il.Emit(OpCodes.Dup);
                    il.Emit(OpCodes.Ldstr, parameter.Alias);

                    EmitSerializeValue(
                        typeBuilder,
                        methodBuilder,
                        invocationContext,
                        invocationContexts,
                        invocationContextsField,
                        parameter.Position,
                        parameter.SourceType,
                        parameterMapping.CleanTargetType,
                        parameter.Converter,
                        serializationProvider,
                        serializationProviderField);

                    var method = typeof(Dictionary<string, string>).GetMethod("Add");
                    il.Emit(OpCodes.Call, method);
                }

                // get the invocation context from the array on the provider
                il.Emit(OpCodes.Ldsfld, invocationContextsField);
                il.Emit(OpCodes.Ldc_I4, invocationContexts.Count);
                il.Emit(OpCodes.Ldelem, typeof(TraceSerializationContext));
                invocationContexts.Add(context);

                il.Emit(OpCodes.Callvirt, typeof(TraceSerializationProvider).GetMethod("ProvideSerialization", BindingFlags.Instance | BindingFlags.Public));
            }
            else
                il.Emit(OpCodes.Ldnull);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Initializes a new instance of the TypeImplementer class.
        /// </summary>
        /// <param name="interfaceType">The type to implement.</param>
        public TypeImplementer(Type interfaceType)
        {
            _interfaceType = interfaceType;
            _contextProvider = ProviderManager.GetProvider<TraceContextProvider>(interfaceType, typeof(TraceContextProviderAttribute), null);
            _serializationProvider = TraceSerializationProvider.GetSerializationProvider(interfaceType);
            _eventAttributeProvider = ProviderManager.GetProvider<EventAttributeProvider>(interfaceType, typeof(EventAttributeProviderAttribute), () => new EventAttributeProvider());

            // only interfaces support context
            if (_contextProvider != null && !_interfaceType.IsInterface)
                throw new InvalidOperationException("Context Providers can only be added to interface-based logs.");

            ImplementType();
        }
        /// <summary>
        /// Initializes a new instance of the TracingProxyImplementer class.
        /// </summary>
        /// <param name="executeType">The type of object to execute.</param>
        /// <param name="logType">The type of object to log.</param>
        /// <param name="callWithActivityScope">True to generate a proxy that wraps an activity scope around all calls.</param>
        public TracingProxyImplementer(Type executeType, Type logType, bool callWithActivityScope)
        {
            _executeType = executeType;
            _callWithActivityScope = callWithActivityScope;
            _serializationProvider = TraceSerializationProvider.GetSerializationProvider(logType);

            // create a log of the given log type
            var log = EventSourceImplementer.GetEventSource(logType);
            _logType = log.GetType();

            CreateMethod = ImplementProxy(log);
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Registers a default TraceSerializationProvider for all event sources.
 /// </summary>
 /// <param name="provider">The provider to register.</param>
 public static void RegisterDefaultProvider(TraceSerializationProvider provider)
 {
     RegisterProvider(null, provider);
 }
Ejemplo n.º 7
0
 /// <summary>
 /// Registers a Serialization Provider for a given event source.
 /// </summary>
 /// <param name="type">The type of event source to register with.</param>
 /// <param name="provider">The provider to register.</param>
 public static void RegisterProvider(Type type, TraceSerializationProvider provider)
 {
     RegisterProvider(type, typeof(TraceSerializationProvider), provider);
 }
Ejemplo n.º 8
0
 public static void RegisterProvider <TLog>(TraceSerializationProvider provider)
 {
     RegisterProvider(typeof(TLog), typeof(TraceSerializationProvider), provider);
 }
Ejemplo n.º 9
0
        /// <summary>
        /// Emits the code needed to properly push an object on the stack,
        /// serializing the value if necessary.
        /// </summary>
        /// <param name="methodBuilder">The method currently being built.</param>
        /// <param name="invocationContext">The invocation context for this call.</param>
        /// <param name="invocationContexts">A list of invocation contexts that will be appended to.</param>
        /// <param name="invocationContextsField">The static field containing the array of invocation contexts at runtime.</param>
        /// <param name="i">The index of the current parameter being pushed.</param>
        /// <param name="sourceType">The type that the parameter is being converted from.</param>
        /// <param name="targetType">The type that the parameter is being converted to.</param>
        /// <param name="serializationProvider">The serialization provider for the current interface.</param>
        /// <param name="serializationProviderField">
        /// The field on the current object that contains the serialization provider at runtime.
        /// This method assume the current object is stored in arg.0.
        /// </param>
        internal static void EmitSerializeValue(
			MethodBuilder methodBuilder,
			InvocationContext invocationContext,
			List<InvocationContext> invocationContexts,
			FieldBuilder invocationContextsField,
			int i,
			Type sourceType,
			Type targetType,
			TraceSerializationProvider serializationProvider,
			FieldBuilder serializationProviderField)
        {
            ILGenerator mIL = methodBuilder.GetILGenerator();

            // if the source type is a reference to the target type, we have to dereference it
            if (sourceType.IsByRef && sourceType.GetElementType() == targetType)
            {
                mIL.Emit(OpCodes.Ldarg, (int)i + 1);
                sourceType = sourceType.GetElementType();
                mIL.Emit(OpCodes.Ldobj, sourceType);
                return;
            }

            // if the types match, just put the argument on the stack
            if (sourceType == targetType)
            {
                mIL.Emit(OpCodes.Ldarg, (int)i + 1);
                return;
            }

            // this is not a match, so convert using the serializer.
            // verify that the target type is a string
            if (targetType != typeof(string))
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot convert type {0} to a type compatible with EventSource", targetType.FullName));

            // for fundamental types, just convert them with ToString and be done with it
            var underlyingType = Nullable.GetUnderlyingType(sourceType) ?? sourceType;
            if (!sourceType.IsGenericParameter && (underlyingType.IsEnum || (underlyingType.IsValueType && underlyingType.Assembly == typeof(string).Assembly)))
            {
                // convert the argument to a string with ToString
                mIL.Emit(OpCodes.Ldarga_S, i + 1);
                mIL.Emit(OpCodes.Call, sourceType.GetMethod("ToString", Type.EmptyTypes));
                return;
            }

            // non-fundamental types use the object serializer
            var context = new TraceSerializationContext(invocationContext, i);
            context.EventLevel = serializationProvider.GetEventLevelForContext(context);
            if (context.EventLevel != null)
            {
                // get the object serializer from the this pointer
                mIL.Emit(OpCodes.Ldsfld, serializationProviderField);

                // load the value
                mIL.Emit(OpCodes.Ldarg, (int)i + 1);

                // if the source type is a reference to the target type, we have to dereference it
                if (sourceType.IsByRef)
                {
                    sourceType = sourceType.GetElementType();
                    mIL.Emit(OpCodes.Ldobj, sourceType);
                }

                // if it's a value type, we have to box it to log it
                if (sourceType.IsGenericParameter || sourceType.IsValueType)
                    mIL.Emit(OpCodes.Box, sourceType);

                // get the invocation context from the array on the provider
                mIL.Emit(OpCodes.Ldsfld, invocationContextsField);
                mIL.Emit(OpCodes.Ldc_I4, invocationContexts.Count);
                mIL.Emit(OpCodes.Ldelem, typeof(TraceSerializationContext));
                invocationContexts.Add(context);

                mIL.Emit(OpCodes.Callvirt, typeof(TraceSerializationProvider).GetMethod("ProvideSerialization", BindingFlags.Instance | BindingFlags.Public));
            }
            else
                mIL.Emit(OpCodes.Ldnull);
        }