Beispiel #1
0
        /// <summary>
        /// Trace traces a function which returns an object with the given span. If the object is a task, the span will be finished when the task completes.
        /// </summary>
        /// <param name="span">The span to use for tracing. The scope for the span should not be set to finish on close.</param>
        /// <param name="func">The function to trace</param>
        /// <param name="onComplete">an optional function to call when the function/task completes. By default exceptions will be added to the span and the span will be finished.</param>
        /// <returns>The result of the function call</returns>
        public static object Trace(this Span span, Func <object> func, Action <Exception> onComplete = null)
        {
            onComplete = onComplete ?? new Action <Exception>(e =>
            {
                if (e != null)
                {
                    span.SetException(e);
                }
                span.Finish();
            });

            try
            {
                var result = func();

                if (result is Task task)
                {
                    var typ         = task.GetType();
                    var genericArgs = GetGenericTypeArguments(typeof(Task <>), typ);
                    if (genericArgs.Length == 1)
                    {
                        if (!_traceTaskMethods.TryGetValue(genericArgs[0], out var traceTask))
                        {
                            traceTask = DynamicMethodBuilder <Func <Span, Task, Action <Exception>, Task> > .CreateMethodCallDelegate(typeof(Extensions), "TraceTask", methodGenericArguments : genericArgs);

                            _traceTaskMethods[genericArgs[0]] = traceTask;
                        }

                        result = traceTask(span, task, onComplete);
                    }
                    else
                    {
                        result = TraceTask(span, task, onComplete);
                    }
                }
                else
                {
                    onComplete(null);
                }

                return(result);
            }
            catch (Exception e)
            {
                onComplete(e);
                throw;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Tries to call an instance method with the specified name, a single parameter, and a return value.
        /// </summary>
        /// <typeparam name="TArg1">The type of the method's single parameter.</typeparam>
        /// <typeparam name="TResult">The type of the method's result value.</typeparam>
        /// <param name="source">The object to call the method on.</param>
        /// <param name="methodName">The name of the method to call.</param>
        /// <param name="arg1">The value to pass as the method's single argument.</param>
        /// <param name="value">The value returned by the method.</param>
        /// <returns><c>true</c> if the method was found, <c>false</c> otherwise.</returns>
        public static bool TryCallMethod <TArg1, TResult>(this object source, string methodName, TArg1 arg1, out TResult value)
        {
            var type       = source.GetType();
            var paramType1 = typeof(TArg1);

            object cachedItem = Cache.GetOrAdd(
                $"{type.AssemblyQualifiedName}.{methodName}.{paramType1.AssemblyQualifiedName}",
                key =>
                DynamicMethodBuilder <Func <object, TArg1, TResult> >
                .CreateMethodCallDelegate(
                    type,
                    methodName,
                    methodParameterTypes: new[] { paramType1 }));

            if (cachedItem is Func <object, TArg1, TResult> func)
            {
                value = func(source, arg1);
                return(true);
            }

            value = default;
            return(false);
        }