Пример #1
0
        public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
        {
            // list of methods on this type according to the underlying ReflectionContext
            MethodInfo[] methods = base.GetMethods(bindingAttr);

            // Optimization: we currently don't support adding nonpublic or static property getters or setters,
            // so if Public or Instance is not set we don't need to check for new properties.
            bool getDeclaredOnly = (bindingAttr & BindingFlags.DeclaredOnly) == BindingFlags.DeclaredOnly;
            bool getInstance     = (bindingAttr & BindingFlags.Instance) == BindingFlags.Instance;
            bool getPublic       = (bindingAttr & BindingFlags.Public) == BindingFlags.Public;

            if (!getPublic || !getInstance)
            {
                return(methods);
            }

            List <MethodInfo> results = new List <MethodInfo>(methods);

            // in runtime reflection hidden methods are always returned in GetMethods
            foreach (PropertyInfo prop in NewProperties)
            {
                results.AddRange(prop.GetAccessors());
            }

            // adding new methods declared on base types
            if (!getDeclaredOnly)
            {
                CustomType?baseType = BaseType as CustomType;
                while (baseType != null)
                {
                    // We shouldn't add a base type method directly on a subtype.
                    // A new method with a different ReflectedType should be used.
                    foreach (PropertyInfo prop in baseType.NewProperties)
                    {
                        PropertyInfo inheritedProperty = new InheritedPropertyInfo(prop, this);
                        results.AddRange(inheritedProperty.GetAccessors());
                    }

                    baseType = baseType.BaseType as CustomType;
                }
            }

            return(results.ToArray());
        }
Пример #2
0
        protected override MethodInfo?GetMethodImpl(string name, BindingFlags bindingAttr, Binder?binder, CallingConventions callConvention, Type[]?types, ParameterModifier[]?modifiers)
        {
            MethodInfo?method = base.GetMethodImpl(name, bindingAttr, binder, callConvention, types, modifiers);

            bool getIgnoreCase   = (bindingAttr & BindingFlags.IgnoreCase) == BindingFlags.IgnoreCase;
            bool getDeclaredOnly = (bindingAttr & BindingFlags.DeclaredOnly) == BindingFlags.DeclaredOnly;
            bool getInstance     = (bindingAttr & BindingFlags.Instance) == BindingFlags.Instance;
            bool getPublic       = (bindingAttr & BindingFlags.Public) == BindingFlags.Public;

            // If the ReflectionContext adds a property with identical name and type to an existing property,
            // the behavior is unspecified.
            // In this implementation, we return the existing method.
            if (!getPublic || !getInstance)
            {
                return(method);
            }

            bool getPropertyGetter = false;
            bool getPropertySetter = false;

            StringComparison comparison = getIgnoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;

            if (name.Length > 4)
            {
                // Right now we don't support adding fabricated indexers on types
                getPropertyGetter = (types == null || types.Length == 0) && name.StartsWith("get_", comparison);

                if (!getPropertyGetter)
                {
                    getPropertySetter = (types == null || types.Length == 1) && name.StartsWith("set_", comparison);
                }
            }

            // not a property getter or setter
            if (!getPropertyGetter && !getPropertySetter)
            {
                return(method);
            }

            // get the target property name by removing "get_" or "set_"
            string targetPropertyName = name.Substring(4);

            List <MethodInfo> matchingMethods = new List <MethodInfo>();

            if (method != null)
            {
                matchingMethods.Add(method);
            }

            // in runtime reflection hidden methods are always returned in GetMethods
            foreach (PropertyInfo newDeclaredProperty in NewProperties)
            {
                if (string.Equals(newDeclaredProperty.Name, targetPropertyName, comparison))
                {
                    MethodInfo?accessor = getPropertyGetter ? newDeclaredProperty.GetGetMethod() : newDeclaredProperty.GetSetMethod();
                    if (accessor != null)
                    {
                        matchingMethods.Add(accessor);
                    }
                }
            }

            // adding new methods declared on base types
            if (!getDeclaredOnly)
            {
                CustomType?baseType = BaseType as CustomType;

                while (baseType != null)
                {
                    // We shouldn't add a base type method directly on a subtype.
                    // A new method with a different ReflectedType should be used.
                    foreach (PropertyInfo newBaseProperty in baseType.NewProperties)
                    {
                        if (string.Equals(newBaseProperty.Name, targetPropertyName, comparison))
                        {
                            PropertyInfo inheritedProperty = new InheritedPropertyInfo(newBaseProperty, this);

                            MethodInfo?accessor = getPropertyGetter ? inheritedProperty.GetGetMethod() : inheritedProperty.GetSetMethod();
                            if (accessor != null)
                            {
                                matchingMethods.Add(accessor);
                            }
                        }
                    }

                    baseType = baseType.BaseType as CustomType;
                }
            }


            if (matchingMethods.Count == 0)
            {
                return(null);
            }

            if (types == null || getPropertyGetter)
            {
                Debug.Assert(types == null || types.Length == 0);

                // matches any signature
                if (matchingMethods.Count == 1)
                {
                    return(matchingMethods[0]);
                }
                else
                {
                    throw new AmbiguousMatchException();
                }
            }
            else
            {
                Debug.Assert(getPropertySetter && types != null && types.Length == 1);

                if (binder == null)
                {
                    binder = Type.DefaultBinder;
                }

                return((MethodInfo?)binder.SelectMethod(bindingAttr, matchingMethods.ToArray(), types, modifiers));
            }
        }