Esempio n. 1
0
        /// <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);
        }
        /// <summary>
        /// Initializes a new instance of the TypeImplementer class.
        /// </summary>
        /// <param name="interfaceType">The type to implement.</param>
        /// <param name="parameterProvider">An optional parameter provider to use when building the type. Used for testing.</param>
        public TypeImplementer(Type interfaceType, TraceParameterProvider parameterProvider = null)
        {
            _interfaceType          = interfaceType;
            _contextProvider        = ProviderManager.GetProvider <TraceContextProvider>(interfaceType, typeof(TraceContextProviderAttribute), null);
            _serializationProvider  = TraceSerializationProvider.GetSerializationProvider(interfaceType);
            _eventAttributeProvider = ProviderManager.GetProvider <EventAttributeProvider>(interfaceType, typeof(EventAttributeProviderAttribute), () => new EventAttributeProvider());
            _traceParameterProvider = parameterProvider ?? TraceParameterProvider.GetParameterProvider(interfaceType);

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

            ImplementType();
        }
Esempio n. 3
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);
 }
Esempio n. 4
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);
 }
Esempio n. 5
0
 public static void RegisterProvider <TLog>(TraceSerializationProvider provider)
 {
     RegisterProvider(typeof(TLog), typeof(TraceSerializationProvider), provider);
 }
Esempio n. 6
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);
            }
        }
Esempio n. 7
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);
            }
        }
Esempio n. 8
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);
		}
Esempio n. 9
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);
			}
		}
		/// <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);
		}
Esempio n. 11
0
		/// <summary>
		/// Initializes a new instance of the TypeImplementer class.
		/// </summary>
		/// <param name="interfaceType">The type to implement.</param>
		/// <param name="parameterProvider">An optional parameter provider to use when building the type. Used for testing.</param>
		public TypeImplementer(Type interfaceType, TraceParameterProvider parameterProvider = null)
		{
			_interfaceType = interfaceType;
			_contextProvider = ProviderManager.GetProvider<TraceContextProvider>(interfaceType, typeof(TraceContextProviderAttribute), null);
			_serializationProvider = TraceSerializationProvider.GetSerializationProvider(interfaceType);
			_eventAttributeProvider = ProviderManager.GetProvider<EventAttributeProvider>(interfaceType, typeof(EventAttributeProviderAttribute), () => new EventAttributeProvider());
			_traceParameterProvider = parameterProvider ?? TraceParameterProvider.GetParameterProvider(interfaceType);

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

			ImplementType();
		}