示例#1
0
        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);
            }
        }
示例#2
0
        public void Prewarm()
        {
            if (fieldAccessor == null)
            {
                fieldAccessor = fieldInfo?.Prewarm();
            }

            if (propertyAccessor == null)
            {
                propertyAccessor = propertyInfo?.Prewarm();
            }

            if (methodInvoker == null)
            {
                methodInvoker = methodInfo?.Prewarm();
            }
        }
示例#3
0
        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);
            }
        }
示例#4
0
        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;
        }