private static void ProcessReflectedMemberInfo(FieldInfo field, ReflectedMemberAttribute attr) { MemberInfo info = null; if (attr.Type == null) { throw new ArgumentException("Reflected member info attributes require Type to be defined"); } if (attr.Name == null) { throw new ArgumentException("Reflected member info attributes require Name to be defined"); } switch (attr) { case ReflectedFieldInfoAttribute rfia: info = GetFieldPropRecursive(rfia.Type, rfia.Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, (type, name, bindingFlags) => type.GetField(name, bindingFlags)); if (info == null) { throw new ArgumentException($"Unable to find field {rfia.Type.FullName}#{rfia.Name}"); } break; case ReflectedPropertyInfoAttribute rpia: info = GetFieldPropRecursive(rpia.Type, rpia.Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, (type, name, bindingFlags) => type.GetProperty(name, bindingFlags)); if (info == null) { throw new ArgumentException($"Unable to find property {rpia.Type.FullName}#{rpia.Name}"); } break; case ReflectedMethodInfoAttribute rmia: if (rmia.Parameters != null) { info = rmia.Type.GetMethod(rmia.Name, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, rmia.Parameters, null); if (info == null) { throw new ArgumentException( $"Unable to find method {rmia.Type.FullName}#{rmia.Name}({string.Join(", ", rmia.Parameters.Select(x => x.FullName))})"); } } else { info = rmia.Type.GetMethod(rmia.Name, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (info == null) { throw new ArgumentException( $"Unable to find method {rmia.Type.FullName}#{rmia.Name}"); } } if (rmia.ReturnType != null && !rmia.ReturnType.IsAssignableFrom(((MethodInfo)info).ReturnType)) { throw new ArgumentException( $"Method {rmia.Type.FullName}#{rmia.Name} has return type {((MethodInfo) info).ReturnType.FullName}, expected {rmia.ReturnType.FullName}"); } break; } if (info == null) { throw new ArgumentException( $"Unable to find member info for {attr.GetType().Name}[{attr.Type.FullName}#{attr.Name}"); } field.SetValue(null, info); }
private static void ProcessReflectedField(FieldInfo field, ReflectedMemberAttribute attr) { MethodInfo delegateMethod = field.FieldType.GetMethod("Invoke"); ParameterInfo[] parameters = delegateMethod.GetParameters(); string trueName = attr.Name ?? field.Name; Type trueType = attr.Type; bool isStatic; if (attr is ReflectedSetterAttribute) { if (delegateMethod.ReturnType != typeof(void) || (parameters.Length != 1 && parameters.Length != 2)) { throw new ArgumentOutOfRangeException(nameof(field), "Delegate for setter must be an action with one or two arguments"); } isStatic = parameters.Length == 1; if (trueType == null && isStatic) { throw new ArgumentException("Static field setters need their type defined", nameof(field)); } if (!isStatic && trueType == null) { trueType = parameters[0].ParameterType; } } else if (attr is ReflectedGetterAttribute) { if (delegateMethod.ReturnType == typeof(void) || (parameters.Length != 0 && parameters.Length != 1)) { throw new ArgumentOutOfRangeException(nameof(field), "Delegate for getter must be an function with one or no arguments"); } isStatic = parameters.Length == 0; if (trueType == null && isStatic) { throw new ArgumentException("Static field getters need their type defined", nameof(field)); } if (!isStatic && trueType == null) { trueType = parameters[0].ParameterType; } } else { throw new ArgumentException($"Field attribute type {attr.GetType().FullName} is invalid", nameof(field)); } BindingFlags bindingFlags = (isStatic ? BindingFlags.Static : BindingFlags.Instance) | BindingFlags.NonPublic | BindingFlags.Public; FieldInfo sourceField = GetFieldPropRecursive(trueType, trueName, bindingFlags, (a, b, c) => a.GetField(b, c)); PropertyInfo sourceProperty = GetFieldPropRecursive(trueType, trueName, bindingFlags, (a, b, c) => a.GetProperty(b, c)); if (sourceField == null && sourceProperty == null) { throw new ArgumentException( $"Unable to find field or property for {trueName} in {trueType.FullName} or its base types", nameof(field)); } var sourceType = sourceField?.FieldType ?? sourceProperty.PropertyType; bool isSetter = attr is ReflectedSetterAttribute; if (sourceProperty != null && isSetter && !sourceProperty.CanWrite) { throw new InvalidOperationException( $"Can't create setter for readonly property {trueName} in {trueType.FullName}"); } if (sourceProperty != null && !isSetter && !sourceProperty.CanRead) { throw new InvalidOperationException( $"Can't create getter for writeonly property {trueName} in {trueType.FullName}"); } var dynMethod = new DynamicMethod((isSetter ? "set" : "get") + "_" + trueType.FullName + "." + trueName, delegateMethod.ReturnType, parameters.Select(x => x.ParameterType).ToArray(), typeof(ReflectedManager).Module, true); ILGenerator il = dynMethod.GetILGenerator(); if (!isStatic) { EmitThis(il, parameters[0].ParameterType, trueType); } if (isSetter) { int val = isStatic ? 0 : 1; il.Emit(OpCodes.Ldarg, val); EmitCast(il, parameters[val].ParameterType, sourceType); if (sourceProperty != null) { il.Emit(sourceProperty.SetMethod.IsStatic ? OpCodes.Call : OpCodes.Callvirt, sourceProperty.SetMethod); } else { il.Emit(isStatic ? OpCodes.Stsfld : OpCodes.Stfld, sourceField); } } else { if (sourceProperty != null) { il.Emit(sourceProperty.GetMethod.IsStatic ? OpCodes.Call : OpCodes.Callvirt, sourceProperty.GetMethod); } else { il.Emit(isStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, sourceField); } EmitCast(il, sourceType, delegateMethod.ReturnType); } il.Emit(OpCodes.Ret); field.SetValue(null, dynMethod.CreateDelegate(field.FieldType)); _log.Trace( $"Reflecting field {field.DeclaringType?.FullName}#{field.Name} with {field.DeclaringType?.FullName}#{field.Name}"); }
private static void ProcessReflectedField(FieldInfo field, ReflectedMemberAttribute attr) { MethodInfo delegateMethod = field.FieldType.GetMethod("Invoke"); ParameterInfo[] parameters = delegateMethod.GetParameters(); string trueName = attr.Name ?? field.Name; Type trueType = attr.Type; bool isStatic; if (attr is ReflectedSetterAttribute) { if (delegateMethod.ReturnType != typeof(void) || (parameters.Length != 1 && parameters.Length != 2)) { throw new ArgumentOutOfRangeException(nameof(field), "Delegate for setter must be an action with one or two arguments"); } isStatic = parameters.Length == 1; if (trueType == null && isStatic) { throw new ArgumentException("Static field setters need their type defined", nameof(field)); } if (!isStatic) { trueType = parameters[0].ParameterType; } } else if (attr is ReflectedGetterAttribute) { if (delegateMethod.ReturnType == typeof(void) || (parameters.Length != 0 && parameters.Length != 1)) { throw new ArgumentOutOfRangeException(nameof(field), "Delegate for getter must be an function with one or no arguments"); } isStatic = parameters.Length == 0; if (trueType == null && isStatic) { throw new ArgumentException("Static field getters need their type defined", nameof(field)); } if (!isStatic) { trueType = parameters[0].ParameterType; } } else { throw new ArgumentException($"Field attribute type {attr.GetType().FullName} is invalid", nameof(field)); } BindingFlags bindingFlags = (isStatic ? BindingFlags.Static : BindingFlags.Instance) | BindingFlags.NonPublic | BindingFlags.Public; FieldInfo sourceField = GetFieldPropRecursive(trueType, trueName, bindingFlags, (a, b, c) => a.GetField(b, c)); PropertyInfo sourceProperty = GetFieldPropRecursive(trueType, trueName, bindingFlags, (a, b, c) => a.GetProperty(b, c)); if (sourceField == null && sourceProperty == null) { throw new ArgumentException( $"Unable to find field or property for {trueName} in {trueType.FullName} or its base types", nameof(field)); } ParameterExpression[] paramExp = parameters.Select(x => Expression.Parameter(x.ParameterType)).ToArray(); MemberExpression fieldExp = sourceField != null ? Expression.Field(isStatic?null : paramExp[0], sourceField) : Expression.Property(isStatic ? null : paramExp[0], sourceProperty); Expression impl; if (attr is ReflectedSetterAttribute) { impl = Expression.Block(Expression.Assign(fieldExp, paramExp[isStatic ? 0 : 1]), Expression.Default(typeof(void))); } else { impl = fieldExp; } field.SetValue(null, Expression.Lambda(impl, paramExp).Compile()); }