public EndMethodDelegate BeforeWrappedMethod(object type,
                                                     object invocationTarget,
                                                     object[] methodArguments,
                                                     uint functionToken)
        {
            if (invocationTarget == null)
            {
                throw new ArgumentException(nameof(invocationTarget));
            }

            var traceMethodInfo = new TraceMethodInfo
            {
                InvocationTarget = invocationTarget,
                MethodArguments  = methodArguments,
                Type             = (Type)type
            };

            var functionInfo = GetFunctionInfoFromCache(functionToken, traceMethodInfo);

            traceMethodInfo.MethodBase = functionInfo.MethodBase;

            if (functionInfo.MethodWrapper == null)
            {
                PrepareMethodWrapper(functionInfo, traceMethodInfo);
            }

            return(functionInfo.MethodWrapper?.BeforeWrappedMethod(traceMethodInfo));
        }
        /// <summary>
        /// GetFunctionInfo MethodBase FromCache
        /// </summary>
        /// <param name="functionToken"></param>
        /// <param name="traceMethodInfo"></param>
        /// <returns></returns>
        private FunctionInfoCache GetFunctionInfoFromCache(uint functionToken, TraceMethodInfo traceMethodInfo)
        {
            var functionInfo = _functionInfosCache.GetOrAdd(functionToken, token =>
            {
                var methodBase        = traceMethodInfo.Type.Module.ResolveMethod((int)token);
                var functionInfoCache = new FunctionInfoCache
                {
                    MethodBase = methodBase
                };
                return(functionInfoCache);
            });

            return(functionInfo);
        }
 public bool CanWrap(TraceMethodInfo traceMethodInfo)
 {
     return(true);
 }
 public EndMethodDelegate BeforeWrappedMethod(TraceMethodInfo traceMethodInfo)
 {
     return(null);
 }
        /// <summary>
        /// Prepare FunctionInfoCache MethodWrapperInfo
        /// </summary>
        /// <param name="functionInfo"></param>
        /// <param name="traceMethodInfo"></param>
        private void PrepareMethodWrapper(FunctionInfoCache functionInfo, TraceMethodInfo traceMethodInfo)
        {
            try
            {
                var assemblyName = traceMethodInfo.Type.Assembly.GetName().Name;
                if (_assemblies.TryGetValue(assemblyName, out var assemblyInfoCache))
                {
                    if (assemblyInfoCache.Assembly == null)
                    {
                        lock (assemblyInfoCache)
                        {
                            if (assemblyInfoCache.Assembly == null)
                            {
                                var path = Path.Combine(_home, $"{assemblyInfoCache.AssemblyName}.dll");
                                if (File.Exists(path))
                                {
                                    var assembly = Assembly.LoadFile(path);
#if NET
                                    AppDomain.CurrentDomain.Load(assembly.GetName());
#endif
                                    assemblyInfoCache.Assembly = assembly;
                                }
                                else
                                {
                                    throw new FileNotFoundException($"FileNotFound Path:{path}");
                                }
                            }
                        }
                    }

                    if (assemblyInfoCache.MethodWrappers == null)
                    {
                        lock (assemblyInfoCache)
                        {
                            if (assemblyInfoCache.MethodWrappers == null)
                            {
                                assemblyInfoCache.MethodWrappers = GetMethodWrappers(assemblyInfoCache.Assembly);
                            }
                        }
                    }

                    foreach (var methodWrapper in assemblyInfoCache.MethodWrappers)
                    {
                        if (methodWrapper.CanWrap(traceMethodInfo))
                        {
                            functionInfo.MethodWrapper = methodWrapper;
                            break;
                        }
                    }
                }
                if (functionInfo.MethodWrapper == null)
                {
                    functionInfo.MethodWrapper = new NoopMethodWrapper();
                }
            }
            catch (BadImageFormatException)
            {
                functionInfo.MethodWrapper = new NoopMethodWrapper();
            }
            catch (FileNotFoundException)
            {
                functionInfo.MethodWrapper = new NoopMethodWrapper();
            }
        }