/// <summary> /// Determines whether or not a particular method body should be replaced at runtime. /// </summary> /// <param name="host">The host instance that contains the target method.</param> /// <param name="context">The context surrounding the method call.</param> /// <returns>Returns <c>true</c> if the method body should be swapped; otherwise, it will return <c>false</c>.</returns> protected override bool ShouldReplace(object host, IInvocationInfo context) { if (MethodReplacementPredicate == null) return true; return MethodReplacementPredicate(context); }
public override object Intercept(IInvocationInfo info) { //typeof(LobbyMenu).GetField ("_hoverButtonInside", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance).SetValue (info.Target, false); try { Type lobbyMenu = typeof(LobbyMenu); if (first) { GUISkin gUISkin7 = ScriptableObject.CreateInstance<GUISkin> (); text = new Texture2D(87, 39); //115, 39 text.LoadImage(System.Reflection.Assembly.GetExecutingAssembly ().GetManifestResourceStream ("ScrollsModLoader.Mods.png").ReadToEnd ()); gUISkin7.button.normal.background = text; gUISkin7.button.hover.background = text; gUISkin7.button.active.background = text; //info.Target.GUISkins.Add (gUISkin5); FieldInfo GUISkins = lobbyMenu.GetField("GUISkins", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance); if (GUISkins == null) Console.WriteLine ("GuiSkins == null"); ((List<GUISkin>)(GUISkins.GetValue(info.Target))).Add(gUISkin7); first = false; } MethodInfo drawHeader = lobbyMenu.GetMethod ("drawHeaderButton", BindingFlags.NonPublic | BindingFlags.Instance); drawHeader.Invoke(info.Target, new object[] {6, "_Settings"}); } catch (Exception exp) { Console.WriteLine (exp); } return info.TargetMethod.Invoke(info.Target, info.Arguments); }
public object DoInvoke(IInvocationInfo info) { Console.WriteLine("Do Invoke - {0}", info.TargetMethod); object result = info.TargetMethod.Invoke(_target, info.Arguments); return(result); }
public object Invoke(IInvocationInfo invocationInfo) { // BEFORE the target method execution var methodInput = CreateMethodInput(invocationInfo); var(msgInputLog, correlationState) = _methodLogMessageFactory.CreateInputMethodLogMessage(methodInput); _logger.Info(msgInputLog); try { // Yield to the next module in the pipeline var returnValue = invocationInfo.Proceed(); // AFTER the target method execution var msgOutputLog = _methodLogMessageFactory.CreateOutputMethodLogMessage(new MethodReturn { ReturnValue = returnValue }, correlationState); _logger.Info(msgOutputLog); return(returnValue); } catch (Exception exp) { var msgOutputLog = _methodLogMessageFactory.CreateOutputMethodLogMessage(new MethodReturn { Exception = exp }, correlationState); _logger.Error(msgOutputLog); throw; } }
public void BeforeInvoke(IInvocationInfo context) { foreach (var invoke in _aroundInvokeList) { invoke.BeforeInvoke(context); } }
/// <summary> /// Initializes the class with a functor that can provide the actual target instance. /// </summary> /// <param name="getActualTarget">The <see cref="Func{TResult}"/> that will provide the target instance that will be used for the method invocation.</param> /// <param name="methodInvoke">The method invoker.</param> /// <param name="realInfo">The <see cref="IInvocationInfo"/> instance that describes the current execution context.</param> internal InvocationInfoInterceptor(IInvocationInfo realInfo, Func<object> getActualTarget, IMethodInvoke<MethodInfo> methodInvoke) : base(methodInvoke) { _getActualTarget = getActualTarget; _realInfo = realInfo; }
public object Invoke(IInvocationInfo invocationInfo) { var typeName = invocationInfo .Method .GetGenericArgumentsName() .First(); if (Kernel.CanGet <IWorkflowAction>(typeName)) { var action = Kernel.Get <IWorkflowAction>(typeName); var parameter = invocationInfo.Arguments.First() + ""; Log.Debug($"Invoking workflow action {typeName}"); if (!action.Evaluate(parameter)) { return(false.ToString()); } Context.AddWorkflowBranch(action.BranchType); return(true.ToString()); } else { using (var e = new ActionNotFoundException(typeName)) Log.Fatal($"Implementation not found for workflow action {typeName}", e); } return(null); }
public void AfterInvoke(IInvocationInfo context, object returnValue) { foreach (var invoke in _aroundInvokeList) { invoke.AfterInvoke(context, returnValue); } }
public object Invoke(IInvocationInfo invocationInfo) { var targetMethodName = _targetMethodName; var candidateMethods = typeof(TInterface).GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(m => m.Name == targetMethodName).ToArray(); var finder = new MethodBaseFinder <MethodInfo>(); var bestMatch = finder.GetBestMatch(candidateMethods, new MethodFinderContext(Option.Some(targetMethodName), invocationInfo.Arguments)); if (!bestMatch.HasValue) { throw new NotImplementedException($"Invocation error: Unable to find a method that is compatible with the '{targetMethodName}' method"); } // Match the signatures var matchingSignature = finder.GetBestMatch(new[] { _targetDelegateMethodSignature }, new MethodFinderContext(Option.None <string>(), invocationInfo.Arguments)); if (!matchingSignature.HasValue) { throw new NotImplementedException($"Invocation error: Unable to find a method that is compatible with the '{targetMethodName}' method"); } var result = _targetDelegateMethodSignature.Invoke(_targetDelegate.Target, invocationInfo.Arguments); return(result); }
/// <summary> /// Returns the provider that is currently attached to the registry. /// </summary> /// <param name="host">The type that is currently being intercepted.</param> /// <param name="info">The <see cref="IInvocationInfo"/> object that describes the invocation context.</param> /// <returns>A <see cref="IMethodReplacementProvider"/> that will determine the code that will be executed once a target method is called.</returns> public static IMethodReplacementProvider GetProvider(object host, IInvocationInfo info) { if (_provider == null) return null; return _provider.CanReplace(host, info) ? _provider : null; }
/// <summary> /// Invokes the currently executing method by using the <paramref name="target"/> /// as the target instance, the <see cref="IInvocationInfo.TargetMethod"/> as the method, /// and uses the <paramref name="arguments"/> for the method /// arguments. /// </summary> /// <param name="info">The <see cref="IInvocationInfo"/> instance that contains information about the method call itself.</param> /// <param name="target">The target instance that will handle the method call.</param> /// <param name="arguments">The arguments that will be used for the actual method call.</param> /// <returns>The return value of the method call.</returns> public static object Proceed(this IInvocationInfo info, object target, params object[] arguments) { MethodBase targetMethod = info.TargetMethod; return(targetMethod.Invoke(target, arguments)); }
/// <summary> /// A method that redirects the method calls to /// the functor instance. /// </summary> /// <param name="info">The <see cref="IInvocationInfo"/> instance that describes the context of the method call.</param> /// <returns>The return value from the target method.</returns> public object Intercept(IInvocationInfo info) { if (_doIntercept == null) throw new NotImplementedException(); return _doIntercept(info); }
void Interpolate(ref IInvocationInfo invocationInfo) { var index = 0; foreach (var argument in invocationInfo.Arguments) { if (argument is string argumentValue) { invocationInfo.Arguments[index] = GetInterpolatedValue(argumentValue); } else if (argument is string[] subArgumentValues) { var subIndex = 0; foreach (var subArgument in subArgumentValues) { (invocationInfo.Arguments[index] as string[])[subIndex] = GetInterpolatedValue(subArgument); subIndex++; } } else { Log.Debug($"Uninterpolable argument type {argument.GetType().Name}"); } index++; } }
/// <summary> /// Invokes the currently executing method by using the <paramref name="target"/> /// as the target instance, the <see cref="IInvocationInfo.TargetMethod"/> as the method, /// and uses the <see cref="IInvocationInfo.Arguments"/> for the method /// arguments. /// </summary> /// <param name="info">The <see cref="IInvocationInfo"/> instance that contains information about the method call itself.</param> /// <param name="target">The target instance that will handle the method call.</param> /// <returns>The return value of the method call.</returns> public static object Proceed(this IInvocationInfo info, object target) { var targetMethod = info.TargetMethod; var arguments = info.Arguments; return(targetMethod.Invoke(target, arguments)); }
public object Intercept(IInvocationInfo info) { var args = string.Join(", ", info.Arguments.Select(x => (x ?? string.Empty).ToString())); Debug.WriteLine(string.Format("Linfu: {0}({1})", info.TargetMethod.Name, args)); return info.TargetMethod.Invoke(info.Target, info.Arguments); }
public object Invoke(IInvocationInfo invocationInfo) { using (_methodIdentityProvider.BeginNextMethodIdentityScope(_mehodIdentityKey)) { return(invocationInfo.Proceed()); } }
/// <summary> /// Wraps the execution of a service operation inside a <see cref="Scope"/>. /// </summary> /// <param name="invocationInfo">The <see cref="IInvocationInfo"/> instance that /// contains information about the current method call.</param> /// <returns>The return value from the method.</returns> public object Invoke(IInvocationInfo invocationInfo) { using (serviceContainer.BeginScope()) { return(invocationInfo.Proceed()); } }
public object Invoke(IInvocationInfo invocationInfo) { if (Context.IsActionIgnored()) { return(""); } if (!Context.Drivers.Any()) { return(invocationInfo.Proceed()); } var coreConfiguration = Context .ConfigurationProvider .Get(CoreConfiguration.Default); object lastResult = null; foreach (var driver in Context.Drivers) { Context.SetBrowser(driver); lastResult = invocationInfo.Proceed(); Context .Driver .WaitForDocumentCompleteness(coreConfiguration.WaitForDocumentCompleteState); } return(lastResult); }
public object Invoke(IInvocationInfo invocationInfo) { var args = string.Join(", ", invocationInfo.Arguments.Select(x => (x ?? string.Empty).ToString())); Debug.WriteLine("LightInject: {0}({1})", invocationInfo.Method, args); return(invocationInfo.Proceed()); }
public IAroundInvoke GetSurroundingImplementation(IInvocationInfo context) { if (Predicate == null) return _around; return Predicate(context) ? _around : null; }
public object Invoke(IInvocationInfo invocationInfo) { if (session.InTransaction) { return invocationInfo.Proceed(); } using (var transaction = session.Connection.BeginTransaction()) { session.InTransaction = true; try { var result = invocationInfo.Proceed(); transaction.Commit(); return result; } catch (Exception) { transaction.Rollback(); throw; } finally { session.InTransaction = false; } } }
public void BeforeInvoke(IInvocationInfo context) { foreach (IAroundInvoke invoke in _aroundInvokeList) { invoke.BeforeInvoke(context); } }
public void AfterInvoke(IInvocationInfo context, object returnValue) { foreach (IAroundInvoke invoke in _aroundInvokeList) { invoke.AfterInvoke(context, returnValue); } }
protected override async Task InvokeAsync(IInvocationInfo invocationInfo) { InterceptedTaskMethod = true; // Before method invocation await base.InvokeAsync(invocationInfo); // After method invocation }
/// <summary> /// Intercepts a method call using the given /// <see cref="IInvocationInfo"/> instance. /// </summary> /// <param name="info">The <see cref="IInvocationInfo"/> instance that will /// contain all the necessary information associated with a /// particular method call.</param> /// <returns>The return value of the target method. If the return type of the target /// method is <see cref="void"/>, then the return value will be ignored.</returns> public virtual object Intercept(IInvocationInfo info) { object target = GetTarget(info); MethodBase method = info.TargetMethod; object[] arguments = info.Arguments; return _methodInvoke.Invoke(target, (MethodInfo) method, arguments); }
/// <summary> /// Intercepts a method call using the given /// <see cref="IInvocationInfo"/> instance. /// </summary> /// <param name="info">The <see cref="IInvocationInfo"/> instance that will /// contain all the necessary information associated with a /// particular method call.</param> /// <returns>The return value of the target method. If the return type of the target /// method is <see cref="Void"/>, then the return value will be ignored.</returns> public virtual object Intercept(IInvocationInfo info) { var target = GetTarget(info); var method = info.TargetMethod; var arguments = info.Arguments; return _methodInvoke.Invoke(target, (MethodInfo)method, arguments); }
public object Invoke(IInvocationInfo invocationInfo) { var returnValue = invocationInfo.Proceed(); var globalCache = _globalCacheFactory.Invoke(); globalCache.NotifyRefresh((ICacheable)invocationInfo.Proxy); return(returnValue); }
public object Invoke(IInvocationInfo invocationInfo) { _logger.Log($"I'm calling method \"{invocationInfo.Method.Name}\"."); var returnValue = invocationInfo.Proceed(); _logger.Log($"Method \"{invocationInfo.Method.Name}\" finished successfully."); return(returnValue); }
public int GetPendingCalls(IInvocationInfo context) { int threadId = Thread.CurrentThread.ManagedThreadId; if (!_counts.ContainsKey(threadId)) return 0; return _counts[threadId].GetPendingCalls(context); }
public object Intercept(IInvocationInfo info) { var args = string.Join(", ", info.Arguments.Select(x => (x ?? string.Empty).ToString())); Trace.WriteLine(string.Format("Linfu: {0}({1})", info.TargetMethod.Name, args)); return(info.TargetMethod.Invoke(info.Target, info.Arguments)); }
/// <summary> /// Intercepts a method call using the given /// <see cref="IInvocationInfo" /> instance. /// </summary> /// <param name="info"> /// The <see cref="IInvocationInfo" /> instance that will /// contain all the necessary information associated with a /// particular method call. /// </param> /// <returns> /// The return value of the target method. If the return type of the target /// method is <see cref="void" />, then the return value will be ignored. /// </returns> public virtual object Intercept(IInvocationInfo info) { var target = GetTarget(info); var method = info.TargetMethod; var arguments = info.Arguments; return(MethodInvoker.Invoke(target, (MethodInfo)method, arguments)); }
public object Intercept(IInvocationInfo info) { var methodName = info.TargetMethod.Name; Console.WriteLine("method '{0}' called", methodName); return info.TargetMethod; }
protected override Task <T> InvokeAsync <T>(IInvocationInfo invocationInfo, Task <T> proceed) { var scope = _methodIdentityProvider.BeginNextMethodIdentityScope(_mehodIdentityKey); proceed.ContinueWith(t => scope.Dispose()); return(proceed); }
protected override async Task <T> InvokeAsync <T>(IInvocationInfo invocationInfo) { InterceptedTaskOfTMethod = true; // Before method invocation var value = await base.InvokeAsync <T>(invocationInfo); // After method invocation return(value); }
/// <summary> /// Determines whether or not a particular method body should be replaced at runtime. /// </summary> /// <param name="host">The host instance that contains the target method.</param> /// <param name="context">The context surrounding the method call.</param> /// <returns>Returns <c>true</c> if the method body should be swapped; otherwise, it will return <c>false</c>.</returns> protected override bool ShouldReplace(object host, IInvocationInfo context) { if (MethodReplacementPredicate == null) { return(true); } return(MethodReplacementPredicate(context)); }
/// <summary> /// Gets the surrounding implemetation for a given <see cref="IInvocationInfo">invocation context</see>. /// </summary> /// <param name="context">The context surrounding the method call.</param> /// <returns>The interceptor that will invoke around the method at runtime.</returns> public IAroundInvoke GetSurroundingImplementation(IInvocationInfo context) { var invokes = new HashSet<IAroundInvoke>(); foreach (var invokePredicate in MethodInvokesAndPredicates.Where(x => x.Value != null && x.Value(context))) { invokes.Add(invokePredicate.Key); } return (invokes.Count > 0) ? new CompositeAroundInvoke(invokes) : null; }
/// <summary> /// Determines whether or not the current method implementation can be replaced. /// </summary> /// <param name="host">The target instance of the method call.</param> /// <param name="context">The <see cref="IInvocationInfo"/> that describes the context of the method call.</param> /// <returns><c>true</c> if the method can be intercepted; otherwise, it will return <c>false</c>.</returns> public bool CanReplace(object host, IInvocationInfo context) { var pendingCalls = _counter.GetPendingCalls(context); if (pendingCalls > 0) return false; return ShouldReplace(host, context); }
/// <summary> /// Returns the provider that is currently attached to the registry. /// </summary> /// <param name="host">The type that is currently being intercepted.</param> /// <param name="info">The <see cref="IInvocationInfo" /> object that describes the invocation context.</param> /// <returns> /// A <see cref="IMethodReplacementProvider" /> that will determine the code that will be executed once a target /// method is called. /// </returns> public static IMethodReplacementProvider GetProvider(object host, IInvocationInfo info) { if (_provider == null) { return(null); } return(_provider.CanReplace(host, info) ? _provider : null); }
/// <summary> /// Intercepts a method call using the given /// <see cref="IInvocationInfo"/> instance. /// </summary> /// <param name="info">The <see cref="IInvocationInfo"/> instance that will /// contain all the necessary information associated with a /// particular method call.</param> /// <returns>The return value of the target method. If the return type of the target /// method is <see cref="void"/>, then the return value will be ignored.</returns> public virtual object Intercept(IInvocationInfo info) { object target = GetTarget(info); MethodBase method = info.TargetMethod; object[] arguments = info.Arguments; return(_methodInvoke.Invoke(target, (MethodInfo)method, arguments)); }
public object Invoke(IInvocationInfo invocationInfo) { if (configuration.DelayerTime.TotalMilliseconds > 0) { Task.Delay((int)configuration.DelayerTime.TotalMilliseconds).Wait(); } return(invocationInfo.Proceed()); }
public object Intercept(IInvocationInfo info) { var methodName = info.TargetMethod.Name; Trace.WriteLine(String.Format("before: {0}", methodName)); var result = info.TargetMethod.Invoke(info.Target, info.Arguments); result = (int)result * 2; Trace.WriteLine(String.Format("after: {0}", methodName)); return result; }
/// <summary> /// Invokes the currently executing method by using the <see cref="IInvocationInfo.Target"/> /// as the target instance, the <see cref="IInvocationInfo.TargetMethod"/> as the method, /// and uses the <see cref="IInvocationInfo.Arguments"/> for the method /// arguments. /// </summary> /// <param name="info">The <see cref="IInvocationInfo"/> instance that contains information about the method call itself.</param> /// <returns>The return value of the method call.</returns> public static object Proceed(this IInvocationInfo info) { MethodBase targetMethod = info.TargetMethod; object target = info.Target; object[] arguments = info.Arguments; return(targetMethod.Invoke(target, arguments)); }
/// <summary> /// A method that redirects the method calls to /// the functor instance. /// </summary> /// <param name="info">The <see cref="IInvocationInfo" /> instance that describes the context of the method call.</param> /// <returns>The return value from the target method.</returns> public object Intercept(IInvocationInfo info) { if (_doIntercept == null) { throw new NotImplementedException(); } return(_doIntercept(info)); }
public IAroundInvoke GetSurroundingImplementation(IInvocationInfo context) { if (Predicate == null) { return(_around); } return(Predicate(context) ? _around : null); }
public bool CanReplace(object host, IInvocationInfo info) { var declaringType = info.TargetMethod.DeclaringType; if (declaringType != typeof(System.Console)) return false; // We're only interested in replacing Console.WriteLine() var targetMethod = info.TargetMethod; return targetMethod.Name == "WriteLine"; }
/// <summary> /// Obtains the <see cref="IInterceptor"/> instance that will be used to replace the current method call. /// </summary> /// <param name="host">The target instance of the method call.</param> /// <param name="context">The <see cref="IInvocationInfo"/> that describes the context of the method call.</param> /// <returns>The interceptor that will intercept the method call itself.</returns> public IInterceptor GetMethodReplacement(object host, IInvocationInfo context) { var pendingCalls = _counter.GetPendingCalls(context); if (pendingCalls > 0) return null; var methodReplacement = GetReplacement(host, context); return new CountingInterceptor(_counter, methodReplacement); }
public override void Apply(IInvocationInfo invocation) { var targetType = invocation.Target.GetType().BaseType !; if (invocation.Target is Base @base && invocation.Method == targetType.GetMethod(nameof(Base.AdvicesByTypes))) { Timestamp = DateTime.UtcNow; Validated = true; }
public InvocationInfo(IInvocationInfo info) { target = info.Target; targetMethod = info.TargetMethod.Name; stackTrace = info.StackTrace; returnType = info.ReturnType; parameterTypes = info.ParameterTypes; typeArguments = info.TypeArguments; arguments = info.Arguments; }
public object Intercept(IInvocationInfo info) { _callCounter.Increment(info); var returnValue = _methodReplacement.Intercept(info); _callCounter.Decrement(info); return returnValue; }
public static MethodInput CreateMethodInput(IInvocationInfo invocationInfo) { return(new MethodInput { Method = invocationInfo.Method, Arguments = invocationInfo.Arguments, Target = invocationInfo.Proxy.Target, TargetType = invocationInfo.Proxy.Target.GetType(), }); }
public object Intercept(IInvocationInfo info) { var methodName = info.TargetMethod.Name; Console.WriteLine("method '{0}' called", methodName); // Replace the input parameter with 42 var result = info.TargetMethod.Invoke(info.Target, new object[]{42}); return result; }
public object Invoke(IInvocationInfo invocation) { var method = invocation.Proxy.Target.GetType().GetMethod(invocation.Method.Name); var joinPoint = new JoinPoint { Arguments = invocation.Arguments, MethodInfo = method, ReturnValue = null, TargetObject = invocation.Proxy.Target, TargetType = invocation.Proxy.Target.GetType(), ExecuteMethodFromProxy = (() => { var value = invocation.Proceed(); return value; }), }; var typesToApply = _types.Where(x => _pointCut.CanApply(joinPoint, x)).ToArray(); if (typesToApply.Length > 0) { var aspectsToApply = typesToApply.Select(x => _container.GetInstance(x) as IAspect).ToArray(); aspectsToApply = aspectsToApply.OrderBy(x => x.GetOrder(joinPoint)).ToArray(); var root = aspectsToApply[0]; var aspect = root; for (var i = 1; i < aspectsToApply.Length; i++) { aspect.NextAspect = aspectsToApply[i]; aspect = aspect.NextAspect; } root.Apply(joinPoint); return joinPoint.ReturnValue; } else { return invocation.Proceed(); } }
public void Increment(IInvocationInfo context) { int threadId = Thread.CurrentThread.ManagedThreadId; lock (_counts) { if (!_counts.ContainsKey(threadId)) _counts[threadId] = new SingleThreadedCallCounter(); _counts[threadId].Increment(context); } }
public void Decrement(IInvocationInfo context) { int threadId = Thread.CurrentThread.ManagedThreadId; if (!_counts.ContainsKey(threadId)) return; lock (_counts) { var counter = _counts[threadId]; counter.Decrement(context); } }
public void Increment(IInvocationInfo context) { var instance = context.Target; var targetMethod = context.TargetMethod; lock (_lock) { if (!_counts.ContainsKey(instance)) _counts[instance] = new Counter<MethodBase>(); _counts[instance].Increment(); } }
private void LogExceptionInformation(IInvocationInfo invocationInfo, Exception ex) { var method = invocationInfo.Method; var target = invocationInfo.Proxy.Target; //You could discover these and determine what to do with it. var parameters = invocationInfo.Arguments; //Add a logger and log this data so we know what is taking so long. //because you have the error, you now have all of the data that was passed to Console.WriteLine($"The Method {method.Name} fauled on Class {target.GetType().FullName} with the following params {string.Join(",", parameters)} because {ex.GetType().FullName}. {ex.ToString()}"); Console.WriteLine(); }
public override object Intercept(IInvocationInfo info) { MethodBase targetMethod = info.TargetMethod; // Intercept calls made only to the IInvocationInfo interface if (targetMethod.DeclaringType != typeof (IInvocationInfo) || targetMethod.Name != "get_Target") return base.Intercept(info); object target = _getActualTarget(); // Replace the proxy with the actual target return target; }
/// <summary> /// Obtains the <see cref="IAroundInvoke"/> instance for the given <paramref name="context"/>. /// </summary> /// <param name="context">The <see cref="IInvocationInfo"/> instance that describes the current method call.</param> /// <returns>An <see cref="IAroundInvoke"/> instance that will be used to wrap a method call or method body.</returns> public static IAroundInvoke GetSurroundingImplementation(IInvocationInfo context) { var resultList = (from p in _providers where p != null let aroundInvoke = p.GetSurroundingImplementation(context) where aroundInvoke != null select aroundInvoke).ToList(); if (resultList.Count == 0) return null; return new CompositeAroundInvoke(resultList); }
public object Invoke(IInvocationInfo invocationInfo) { try { // Perform logic before invoking the target method var returnValue = invocationInfo.Proceed(); // Perform logic after invoking the target method return returnValue; } catch (Exception ex) { LogExceptionInformation(invocationInfo, ex); throw; } }