protected void AddWoopsaMethod(MethodDescription methodDescription) { try { new WoopsaMethod(this, methodDescription.MethodInfo.Name, methodDescription.WoopsaReturnType, methodDescription.WoopsaArguments, CreateWoopsaMethodInvokeDelegate(methodDescription)); } catch (Exception) { // This can happen when methods are overloaded. This isn't supported in Woopsa. // Ignore silently, the method won't be published } }
protected virtual WoopsaMethodInvoke CreateWoopsaMethodInvokeDelegate( MethodDescription methodDescription) { return((args) => { try { var typedArguments = new object[methodDescription.Arguments.Count]; for (var i = 0; i < methodDescription.Arguments.Count; i++) { typedArguments[i] = methodDescription.Arguments[i].Converter.FromWoopsaValue( (IWoopsaValue)args[i], methodDescription.Arguments[i].Type); } if (methodDescription.MethodInfo.ReturnType == typeof(void)) { methodDescription.MethodInfo.Invoke(TargetObject, typedArguments); return null; } else { return methodDescription.Converter.ToWoopsaValue( methodDescription.MethodInfo.Invoke(TargetObject, typedArguments), methodDescription.WoopsaReturnType, GetTimeStamp()); } } catch (TargetInvocationException e) { // Because we are invoking using reflection, the // exception that is actually thrown is a TargetInvocationException // containing the actual exception if (e.InnerException != null) { throw e.InnerException; } else { throw; } } }); }
protected virtual WoopsaMethodInvoke CreateWoopsaMethodInvokeDelegate( MethodDescription methodDescription) { return((args) => { var typedArguments = new object[methodDescription.Arguments.Count]; for (var i = 0; i < methodDescription.Arguments.Count; i++) { typedArguments[i] = methodDescription.Arguments[i].Converter.FromWoopsaValue( (IWoopsaValue)args[i], methodDescription.Arguments[i].Type); } if (methodDescription.MethodInfo.ReturnType == typeof(void)) { methodDescription.MethodInfo.Invoke(TargetObject, typedArguments); return null; } else { return methodDescription.Converter.ToWoopsaValue( methodDescription.MethodInfo.Invoke(TargetObject, typedArguments), methodDescription.WoopsaReturnType, GetTimeStamp()); } }); }
public static void ReflectMethods( Type targetType, MethodDescriptions methodDescriptions, WoopsaConverters customValueTypeConverters = null) { const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; List <MethodInfo> methods = new List <MethodInfo>(targetType.GetMethods(flags)); foreach (Type inter in targetType.GetInterfaces()) { foreach (MethodInfo method in inter.GetMethods(flags)) { if (!methods.Contains(method)) { methods.Add(method); } } } foreach (var methodInfo in methods) { WoopsaConverter converter; WoopsaValueTypeAttribute attribute = GetCustomAttribute <WoopsaValueTypeAttribute>(methodInfo); WoopsaValueType woopsaReturnType; bool isValidWoopsaMethod = false; isValidWoopsaMethod = InferWoopsaType(customValueTypeConverters, methodInfo.ReturnType, out woopsaReturnType, out converter); if (attribute != null) { woopsaReturnType = attribute.ValueType; isValidWoopsaMethod = true; } if (isValidWoopsaMethod) { bool argumentsTypeCompatible = true; ArgumentDescriptions arguments = new ArgumentDescriptions(); int parameterIndex = 0; foreach (var parameter in methodInfo.GetParameters()) { WoopsaConverter argumentConverter; WoopsaValueType argumentType; if (InferWoopsaType(customValueTypeConverters, parameter.ParameterType, out argumentType, out argumentConverter)) { string parameterName; parameterName = parameter.Name; if (string.IsNullOrEmpty(parameterName)) { if (typeof(Array).IsAssignableFrom(targetType)) { if (methodInfo.Name == "Set") { if (parameterIndex == 0) { parameterName = "index"; } else if (parameterIndex == 1) { parameterName = "value"; } } else if (methodInfo.Name == "Get") { if (parameterIndex == 0) { parameterName = "index"; } } } if (parameterName == null) { parameterName = "p" + parameterIndex.ToString(); } } ArgumentDescription newArgument = new ArgumentDescription( new WoopsaMethodArgumentInfo(parameterName, argumentType), parameter.ParameterType, argumentConverter); arguments.Add(newArgument); } else { argumentsTypeCompatible = false; break; } parameterIndex++; } if (argumentsTypeCompatible) { MethodDescription newMethod = new MethodDescription( woopsaReturnType, arguments, methodInfo, converter); methodDescriptions.Add(newMethod); } } } }