/// <summary>Returns the desired method to call and it's parameters types, as specified in the payload parameter.</summary> /// <param name="payload">The payload specifying the parameters and the method that wants to be called. </param> /// <param name="bindingFlags">The flags that will be used for trying to get the desired method through reflection.</param> /// <param name="settingItem">The object from which obtain the method to be called. </param> /// <returns>A SettingInfo object with the method to be called and an array with it's type parameters". </returns> public static SetInfo GetDesiredMethod(Payload payload, BindingFlags bindingFlags, SettingItem settingItem) { // Get the parameter types to get the right overload. Type[] paramTypes = Type.EmptyTypes; if (payload.Parameters != null) { paramTypes = payload.Parameters.Select(p => p.GetType()).ToArray(); } MethodInfo method = settingItem.GetType().GetMethod(payload.Method, bindingFlags, null, paramTypes, null); if (method == null) { // Method can't be found matching the parameter types, get any method with the same name // and let .Invoke worry about the parameters. try { method = settingItem.GetType().GetMethod(payload.Method, bindingFlags); } catch (AmbiguousMatchException) { method = null; } if (method == null) { throw new SettingFailedException("Unknown method " + payload.Method); } } if (!method.IsExposed()) { // Only use those with the "Exposed" attribute. throw new SettingFailedException("Not an exposed method " + payload.Method); } return(new SetInfo(method, paramTypes)); }
/// <summary> /// Applies a payload, by invoking the method identified in <c>payload</c>. /// </summary> /// <param name="payload">The payload.</param> /// <returns>The result.</returns> public static Result Apply(Payload payload) { Result result = new Result(payload); try { if (string.IsNullOrEmpty(payload.SettingId)) { throw new SettingFailedException("settingID is required."); } if (string.IsNullOrEmpty(payload.Method)) { throw new SettingFailedException("method is required."); } SettingItem settingItem; // Cache the instance, incase it's re-used. if (!settingCache.TryGetValue(payload.SettingId, out settingItem)) { settingItem = new SettingItem(payload.SettingId, SettingHandler.DryRun); settingCache[payload.SettingId] = settingItem; } payload.SettingItem = settingItem; // Get the parameter types to get the right overload. Type[] paramTypes = Type.EmptyTypes; if (payload.Parameters != null) { paramTypes = payload.Parameters.Select(p => p.GetType()).ToArray(); } BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase; MethodInfo method = settingItem.GetType().GetMethod(payload.Method, bindingFlags, null, paramTypes, null); if (method == null) { // Method can't be found matching the parameter types, get any method with the same name // and let .Invoke worry about the parameters. try { method = settingItem.GetType().GetMethod(payload.Method, bindingFlags); } catch (AmbiguousMatchException) { method = null; } if (method == null) { throw new SettingFailedException("Unknown method " + payload.Method); } } if (!method.IsExposed()) { // Only use those with the "Exposed" attribute. throw new SettingFailedException("Not an exposed method " + payload.Method); } try { result.ReturnValue = method.Invoke(settingItem, payload.Parameters); if (!(payload.Async ?? true)) { settingItem.WaitForCompletion(5); } } catch (Exception e) { // Catching general exceptions is ok with .NET 4 because corrupted state exceptions aren't caught. throw new SettingFailedException(null, e.InnerException ?? e); } } catch (SettingFailedException e) { result.IsError = true; result.ErrorMessage = e.Message; } return(result); }