private static void ProcessReflectedMethod(FieldInfo field, ReflectedMethodAttribute attr) { MethodInfo delegateMethod = field.FieldType.GetMethod("Invoke"); ParameterInfo[] parameters = delegateMethod.GetParameters(); Type trueType = attr.Type; Type[] trueParameterTypes; if (attr is ReflectedStaticMethodAttribute) { trueParameterTypes = parameters.Select(x => x.ParameterType).ToArray(); } else { trueType = trueType ?? parameters[0].ParameterType; trueParameterTypes = parameters.Skip(1).Select(x => x.ParameterType).ToArray(); } MethodInfo methodInstance = trueType.GetMethod(attr.Name ?? field.Name, (attr is ReflectedStaticMethodAttribute ? BindingFlags.Static : BindingFlags.Instance) | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, trueParameterTypes, null); if (methodInstance == null) { string methodType = attr is ReflectedStaticMethodAttribute ? "static" : "instance"; string methodParams = string.Join(", ", trueParameterTypes.Select(x => x.Name)); throw new NoNullAllowedException( $"Unable to find {methodType} method {attr.Name ?? field.Name} in type {trueType.FullName} with parameters {methodParams}"); } if (attr is ReflectedStaticMethodAttribute) { field.SetValue(null, Delegate.CreateDelegate(field.FieldType, methodInstance)); } else { ParameterExpression[] paramExp = parameters.Select(x => Expression.Parameter(x.ParameterType)).ToArray(); field.SetValue(null, Expression.Lambda(Expression.Call(paramExp[0], methodInstance, paramExp.Skip(1)), paramExp) .Compile()); } }
private static void ProcessReflectedMethod(FieldInfo field, ReflectedMethodAttribute attr) { MethodInfo delegateMethod = field.FieldType.GetMethod("Invoke"); ParameterInfo[] parameters = delegateMethod.GetParameters(); Type trueType = attr.Type; Type[] trueParameterTypes; if (attr is ReflectedStaticMethodAttribute) { trueParameterTypes = parameters.Select(x => x.ParameterType).ToArray(); } else { trueType = trueType ?? parameters[0].ParameterType; trueParameterTypes = parameters.Skip(1).Select(x => x.ParameterType).ToArray(); } var invokeTypes = new Type[trueParameterTypes.Length]; for (var i = 0; i < invokeTypes.Length; i++) { invokeTypes[i] = attr.OverrideTypes?[i] ?? trueParameterTypes[i]; } MethodInfo methodInstance = trueType.GetMethod(attr.Name ?? field.Name, (attr is ReflectedStaticMethodAttribute ? BindingFlags.Static : BindingFlags.Instance) | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, invokeTypes, null); if (methodInstance == null) { string methodType = attr is ReflectedStaticMethodAttribute ? "static" : "instance"; string methodParams = string.Join(", ", trueParameterTypes.Select(x => x.Name)); throw new NoNullAllowedException( $"Unable to find {methodType} method {attr.Name ?? field.Name} in type {trueType.FullName} with parameters {methodParams}"); } if (attr is ReflectedStaticMethodAttribute) { if (attr.OverrideTypes != null) { ParameterExpression[] paramExp = parameters.Select(x => Expression.Parameter(x.ParameterType)).ToArray(); var argExp = new Expression[invokeTypes.Length]; for (var i = 0; i < argExp.Length; i++) { if (invokeTypes[i] != paramExp[i].Type) { argExp[i] = Expression.Convert(paramExp[i], invokeTypes[i]); } else { argExp[i] = paramExp[i]; } } field.SetValue(null, Expression.Lambda(Expression.Call(methodInstance, argExp), paramExp) .Compile()); } else { field.SetValue(null, Delegate.CreateDelegate(field.FieldType, methodInstance)); } } else { ParameterExpression[] paramExp = parameters.Select(x => Expression.Parameter(x.ParameterType)).ToArray(); var argExp = new Expression[invokeTypes.Length]; for (var i = 0; i < argExp.Length; i++) { if (invokeTypes[i] != paramExp[i + 1].Type) { argExp[i] = Expression.Convert(paramExp[i + 1], invokeTypes[i]); } else { argExp[i] = paramExp[i + 1]; } } Debug.Assert(methodInstance.DeclaringType != null); Expression instanceExp = paramExp[0].Type != methodInstance.DeclaringType ? Expression.Convert(paramExp[0], methodInstance.DeclaringType) : (Expression)paramExp[0]; field.SetValue(null, Expression.Lambda(Expression.Call(instanceExp, methodInstance, argExp), paramExp) .Compile()); _log.Trace( $"Reflecting field {field.DeclaringType?.FullName}#{field.Name} with {methodInstance.DeclaringType?.FullName}#{methodInstance.Name}"); } }