public object Get(object target) { EnsureReady(target); switch (source) { case Source.Field: if (fieldAccessor == null) { fieldAccessor = fieldInfo.Prewarm(); } return(fieldAccessor.GetValue(target)); case Source.Property: if (propertyAccessor == null) { propertyAccessor = propertyInfo.Prewarm(); } return(propertyAccessor.GetValue(target)); case Source.Method: throw new NotSupportedException("Member is a method. Consider using 'Invoke' instead."); case Source.Constructor: throw new NotSupportedException("Member is a constructor. Consider using 'Invoke' instead."); default: throw new UnexpectedEnumValueException <Source>(source); } }
public void Prewarm() { if (fieldAccessor == null) { fieldAccessor = fieldInfo?.Prewarm(); } if (propertyAccessor == null) { propertyAccessor = propertyInfo?.Prewarm(); } if (methodInvoker == null) { methodInvoker = methodInfo?.Prewarm(); } }
public object Set(object target, object value) { EnsureReady(target); // When setting, we return the assigned value, not the updated field or property. // This is consistent with C# language behaviour: https://msdn.microsoft.com/en-us/library/sbkb459w.aspx // "The assignment operator (=) [...] returns the value as its result" // See confirmation here: https://dotnetfiddle.net/n4RZcW switch (source) { case Source.Field: if (fieldAccessor == null) { fieldAccessor = fieldInfo.Prewarm(); } fieldAccessor.SetValue(target, value); return(value); case Source.Property: if (propertyAccessor == null) { propertyAccessor = propertyInfo.Prewarm(); } propertyAccessor.SetValue(target, value); return(value); case Source.Method: throw new NotSupportedException("Member is a method."); case Source.Constructor: throw new NotSupportedException("Member is a constructor."); default: throw new UnexpectedEnumValueException <Source>(source); } }
public void Reflect() { // Cannot happen from the constructor, but will occur // if the type doesn't exist and fails to be deserialized if (targetType == null) { if (targetTypeName != null) { throw new MissingMemberException(targetTypeName, name); } else { throw new MissingMemberException("Target type not found."); } } _source = Source.Unknown; _fieldInfo = null; _propertyInfo = null; _methodInfo = null; _constructorInfo = null; fieldAccessor = null; propertyAccessor = null; methodInvoker = null; MemberInfo[] candidates; try { candidates = targetType.GetExtendedMember(name, SupportedMemberTypes, SupportedBindingFlags); } catch (NotSupportedException e) { throw new InvalidOperationException($"An error occured when trying to reflect the member '{name}' of the type '{targetType.FullName}' in a '{GetType().Name}' unit. Supported member types: {SupportedMemberTypes}, supported binding flags: {SupportedBindingFlags}", e); } if (candidates.Length == 0) // Not found, check if it might have been renamed { var renamedMembers = RuntimeCodebase.RenamedMembers(targetType); string newName; if (renamedMembers.TryGetValue(name, out newName)) { name = newName; try { candidates = targetType.GetExtendedMember(name, SupportedMemberTypes, SupportedBindingFlags); } catch (NotSupportedException e) { throw new InvalidOperationException($"An error occured when trying to reflect the renamed member '{name}' of the type '{targetType.FullName}' in a '{GetType().Name}' unit. Supported member types: {SupportedMemberTypes}, supported binding flags: {SupportedBindingFlags}", e); } } } if (candidates.Length == 0) // Nope, not even, abort { throw new MissingMemberException($"No matching member found: '{targetType.Name}.{name}'"); } MemberTypes?memberType = null; foreach (var candidate in candidates) { if (memberType == null) { memberType = candidate.MemberType; } else if (candidate.MemberType != memberType && !candidate.IsExtensionMethod()) { // This theoretically shouldn't happen according to the .NET specification, I believe Debug.LogWarning($"Multiple members with the same name are of a different type: '{targetType.Name}.{name}'"); break; } } switch (memberType) { case MemberTypes.Field: ReflectField(candidates); break; case MemberTypes.Property: ReflectProperty(candidates); break; case MemberTypes.Method: ReflectMethod(candidates); break; case MemberTypes.Constructor: ReflectConstructor(candidates); break; default: throw new UnexpectedEnumValueException <MemberTypes>(memberType.Value); } isReflected = true; }