PropertyDoesNotHaveAccessor() static private method

ArgumentException with message like "The property '{0}' has no 'get' or 'set' accessors"
static private PropertyDoesNotHaveAccessor ( object p0, string paramName ) : Exception
p0 object
paramName string
return Exception
示例#1
0
        public static MemberExpression Property(Expression expression, PropertyInfo property)
        {
            ContractUtils.RequiresNotNull(property, "property");

            MethodInfo mi = property.GetGetMethod(true) ?? property.GetSetMethod(true);

            if (mi == null)
            {
                throw Error.PropertyDoesNotHaveAccessor(property);
            }

            if (mi.IsStatic)
            {
                ContractUtils.Requires(expression == null, "expression", Strings.OnlyStaticPropertiesHaveNullInstance);
            }
            else
            {
                ContractUtils.Requires(expression != null, "property", Strings.OnlyStaticPropertiesHaveNullInstance);
                RequiresCanRead(expression, "expression");
                if (!TypeUtils.IsValidInstanceType(property, expression.Type))
                {
                    throw Error.PropertyNotDefinedForType(property, expression.Type);
                }
            }
            return(MemberExpression.Make(expression, property));
        }
示例#2
0
        // CTS places no restrictions on properties (see ECMA-335 8.11.3),
        // so we validate that the property conforms to CLS rules here.
        //
        // TODO: Do we still need all of this now that we take PropertyInfo?
        // Does reflection help us out at all? Expression.Property skips all of
        // these checks, so either it needs more checks or we need less here.
        private static void ValidateIndexedProperty(Expression instance, PropertyInfo property, ref ReadOnlyCollection <Expression> argList)
        {
            // If both getter and setter specified, all their parameter types
            // should match, with exception of the last setter parameter which
            // should match the type returned by the get method.
            // Accessor parameters cannot be ByRef.

            ContractUtils.RequiresNotNull(property, "property");
            ContractUtils.Requires(!property.PropertyType.IsByRef, "property", Strings.PropertyCannotHaveRefType);
            ContractUtils.Requires(property.PropertyType != typeof(void), "property", Strings.PropertyTypeCannotBeVoid);

            ParameterInfo[] getParameters = null;
            MethodInfo      getter        = property.GetGetMethod(true);

            if (getter != null)
            {
                getParameters = getter.GetParametersCached();
                ValidateAccessor(instance, getter, getParameters, ref argList);
            }

            MethodInfo setter = property.GetSetMethod(true);

            if (setter != null)
            {
                ParameterInfo[] setParameters = setter.GetParametersCached();
                ContractUtils.Requires(setParameters.Length > 0, "property", Strings.SetterHasNoParams);

                // valueType is the type of the value passed to the setter (last parameter)
                Type valueType = setParameters[setParameters.Length - 1].ParameterType;
                ContractUtils.Requires(!valueType.IsByRef, "property", Strings.PropertyCannotHaveRefType);
                ContractUtils.Requires(setter.ReturnType == typeof(void), "property", Strings.SetterMustBeVoid);
                ContractUtils.Requires(property.PropertyType == valueType, "property", Strings.PropertyTyepMustMatchSetter);

                if (getter != null)
                {
                    ContractUtils.Requires(!(getter.IsStatic ^ setter.IsStatic), "property", Strings.BothAccessorsMustBeStatic);
                    ContractUtils.Requires(getParameters.Length == setParameters.Length - 1, "property", Strings.IndexesOfSetGetMustMatch);

                    for (int i = 0; i < getParameters.Length; i++)
                    {
                        ContractUtils.Requires(getParameters[i].ParameterType == setParameters[i].ParameterType, "property", Strings.IndexesOfSetGetMustMatch);
                    }
                }
                else
                {
                    ValidateAccessor(instance, setter, setParameters.RemoveLast(), ref argList);
                }
            }

            if (getter == null && setter == null)
            {
                throw Error.PropertyDoesNotHaveAccessor(property);
            }
        }
示例#3
0
        public static MemberExpression Property(Expression expression, PropertyInfo property)
        {
            ContractUtils.RequiresNotNull(property, nameof(property));

            var mi = property.GetGetMethod(nonPublic: true);

            if (mi == null)
            {
                mi = property.GetSetMethod(nonPublic: true);

                if (mi == null)
                {
                    throw Error.PropertyDoesNotHaveAccessor(property, nameof(property));
                }

                if (mi.GetParameters().Length != 1)
                {
                    throw Error.IncorrectNumberOfMethodCallArguments(mi, nameof(property));
                }
            }
            else if (mi.GetParameters().Length != 0)
            {
                throw Error.IncorrectNumberOfMethodCallArguments(mi, nameof(property));
            }

            if (mi.IsStatic)
            {
                if (expression != null)
                {
                    throw Error.OnlyStaticPropertiesHaveNullInstance(nameof(expression));
                }
            }
            else
            {
                if (expression == null)
                {
                    throw Error.OnlyStaticPropertiesHaveNullInstance(nameof(property));
                }

                ExpressionUtils.RequiresCanRead(expression, nameof(expression));
                if (!TypeUtils.IsValidInstanceType(property, expression.Type))
                {
                    throw Error.PropertyNotDefinedForType(property, expression.Type, nameof(property));
                }
            }

            ValidateMethodInfo(mi, nameof(property));

            return(MemberExpression.Make(expression, property));
        }
示例#4
0
        public static MemberExpression Property(Expression expression, PropertyInfo property)
        {
            ContractUtils.RequiresNotNull(property, "property");

            MethodInfo mi = property.GetGetMethod(true);

            if (mi == null)
            {
                mi = property.GetSetMethod(true);

                if (mi == null)
                {
                    throw Error.PropertyDoesNotHaveAccessor(property);
                }
                else if (mi.GetParametersCached().Length != 1)
                {
                    throw Error.IncorrectNumberOfMethodCallArguments(mi);
                }
            }
            else if (mi.GetParametersCached().Length != 0)
            {
                throw Error.IncorrectNumberOfMethodCallArguments(mi);
            }

            if (mi.IsStatic)
            {
                if (expression != null)
                {
                    throw new ArgumentException(Strings.OnlyStaticPropertiesHaveNullInstance, "expression");
                }
            }
            else
            {
                if (expression == null)
                {
                    throw new ArgumentException(Strings.OnlyStaticPropertiesHaveNullInstance, "property");
                }
                RequiresCanRead(expression, "expression");
                if (!TypeUtils.IsValidInstanceType(property, expression.Type))
                {
                    throw Error.PropertyNotDefinedForType(property, expression.Type);
                }
            }

            return(MemberExpression.Make(expression, property));
        }
示例#5
0
        // CTS places no restrictions on properties (see ECMA-335 8.11.3),
        // so we validate that the property conforms to CLS rules here.
        //
        // Does reflection help us out at all? Expression.Property skips all of
        // these checks, so either it needs more checks or we need less here.
        private static void ValidateIndexedProperty(Expression instance, PropertyInfo property, ref ReadOnlyCollection <Expression> argList)
        {
            // If both getter and setter specified, all their parameter types
            // should match, with exception of the last setter parameter which
            // should match the type returned by the get method.
            // Accessor parameters cannot be ByRef.

            ContractUtils.RequiresNotNull(property, "property");
            if (property.PropertyType.IsByRef)
            {
                throw Error.PropertyCannotHaveRefType();
            }

            if (property.PropertyType == typeof(void))
            {
                throw Error.PropertyTypeCannotBeVoid();
            }

            ParameterInfo[] getParameters = null;
            var             getter        = property.GetGetMethod(true);

            if (getter != null)
            {
                getParameters = getter.GetParameters();
                ValidateAccessor(instance, getter, getParameters, ref argList);
            }

            var setter = property.GetSetMethod(true);

            if (setter != null)
            {
                var setParameters = setter.GetParameters();
                if (setParameters.Length == 0)
                {
                    throw Error.SetterHasNoParams();
                }

                // valueType is the type of the value passed to the setter (last parameter)
                var valueType = setParameters[setParameters.Length - 1].ParameterType;
                if (valueType.IsByRef)
                {
                    throw Error.PropertyCannotHaveRefType();
                }

                if (setter.ReturnType != typeof(void))
                {
                    throw Error.SetterMustBeVoid();
                }

                if (property.PropertyType != valueType)
                {
                    throw Error.PropertyTyepMustMatchSetter();
                }

                if (getter != null)
                {
                    if (getter.IsStatic ^ setter.IsStatic)
                    {
                        throw Error.BothAccessorsMustBeStatic();
                    }

                    if (getParameters.Length != setParameters.Length - 1)
                    {
                        throw Error.IndexesOfSetGetMustMatch();
                    }

                    for (var i = 0; i < getParameters.Length; i++)
                    {
                        if (getParameters[i].ParameterType != setParameters[i].ParameterType)
                        {
                            throw Error.IndexesOfSetGetMustMatch();
                        }
                    }
                }
                else
                {
                    ValidateAccessor(instance, setter, setParameters.RemoveLast(), ref argList);
                }
            }

            if (getter == null && setter == null)
            {
                throw Error.PropertyDoesNotHaveAccessor(property);
            }
        }
        // CTS places no restrictions on properties (see ECMA-335 8.11.3),
        // so we validate that the property conforms to CLS rules here.
        //
        // Does reflection help us out at all? Expression.Property skips all of
        // these checks, so either it needs more checks or we need less here.
        private static void ValidateIndexedProperty(Expression?instance, PropertyInfo indexer, string paramName, ref ReadOnlyCollection <Expression> argList)
        {
            // If both getter and setter specified, all their parameter types
            // should match, with exception of the last setter parameter which
            // should match the type returned by the get method.
            // Accessor parameters cannot be ByRef.

            ContractUtils.RequiresNotNull(indexer, paramName);
            if (indexer.PropertyType.IsByRef)
            {
                throw Error.PropertyCannotHaveRefType(paramName);
            }
            if (indexer.PropertyType == typeof(void))
            {
                throw Error.PropertyTypeCannotBeVoid(paramName);
            }

            ParameterInfo[]? getParameters = null;
            MethodInfo?getter = indexer.GetGetMethod(nonPublic: true);

            if (getter != null)
            {
                if (getter.ReturnType != indexer.PropertyType)
                {
                    throw Error.PropertyTypeMustMatchGetter(paramName);
                }

                getParameters = getter.GetParametersCached();
                ValidateAccessor(instance, getter, getParameters, ref argList, paramName);
            }

            MethodInfo?setter = indexer.GetSetMethod(nonPublic: true);

            if (setter != null)
            {
                ParameterInfo[] setParameters = setter.GetParametersCached();
                if (setParameters.Length == 0)
                {
                    throw Error.SetterHasNoParams(paramName);
                }

                // valueType is the type of the value passed to the setter (last parameter)
                Type valueType = setParameters[setParameters.Length - 1].ParameterType;
                if (valueType.IsByRef)
                {
                    throw Error.PropertyCannotHaveRefType(paramName);
                }
                if (setter.ReturnType != typeof(void))
                {
                    throw Error.SetterMustBeVoid(paramName);
                }
                if (indexer.PropertyType != valueType)
                {
                    throw Error.PropertyTypeMustMatchSetter(paramName);
                }

                if (getter != null)
                {
                    if (getter.IsStatic ^ setter.IsStatic)
                    {
                        throw Error.BothAccessorsMustBeStatic(paramName);
                    }
                    if (getParameters !.Length != setParameters.Length - 1)
                    {
                        throw Error.IndexesOfSetGetMustMatch(paramName);
                    }

                    for (int i = 0; i < getParameters.Length; i++)
                    {
                        if (getParameters[i].ParameterType != setParameters[i].ParameterType)
                        {
                            throw Error.IndexesOfSetGetMustMatch(paramName);
                        }
                    }
                }
                else
                {
                    ValidateAccessor(instance, setter, setParameters.RemoveLast(), ref argList, paramName);
                }
            }
            else if (getter == null)
            {
                throw Error.PropertyDoesNotHaveAccessor(indexer, paramName);
            }
        }
示例#7
0
        /// <summary>
        /// Creates a <see cref="MemberInitializer"/> binding the specified value to the given member.
        /// </summary>
        /// <param name="member">The <see cref="MemberInfo"/> for the member which is being assigned to.</param>
        /// <param name="expression">The value to be assigned to <paramref name="member"/>.</param>
        /// <returns>The created <see cref="MemberInitializer"/>.</returns>
        public static MemberInitializer MemberInitializer(MemberInfo member, Expression expression)
        {
            RequiresNotNull(member, nameof(member));

            //
            // NB: System.Linq.Expressions fails to checks for static members in ValidateSettableFieldOrPropertyMember.
            //
            //       class Foo { public static int Bar { get; set; } }
            //
            //       Expression.Lambda<Func<Foo>>(
            //         Expression.MemberInit(
            //           Expression.New(typeof(Foo)),
            //           Expression.Bind(typeof(Foo).GetProperty("Bar"), Expression.Constant(1))
            //         )
            //       ).Compile()
            //
            //     throws 'System.Security.VerificationException: Operation could destabilize the runtime.'
            //
            //     We add this check here.
            //

            Type memberType;

            switch (member)
            {
            case FieldInfo f:
                memberType = f.FieldType;

                if (f.IsStatic)
                {
                    throw Error.MemberInitializerMemberMustNotBeStatic(member.Name);
                }

                break;

            case PropertyInfo p:
                memberType = p.PropertyType;

                var accessor = p.GetGetMethod(nonPublic: true) ?? p.GetSetMethod(nonPublic: true);
                if (accessor == null)
                {
                    throw LinqError.PropertyDoesNotHaveAccessor(p);
                }

                if (accessor.IsStatic)
                {
                    throw Error.MemberInitializerMemberMustNotBeStatic(member.Name);
                }

                if (p.GetIndexParameters().Length > 0)
                {
                    throw Error.MemberInitializerMemberMustNotBeIndexer(member.Name);
                }

                break;

            default:
                throw LinqError.ArgumentMustBeFieldInfoOrPropertInfo();
            }

            RequiresCanRead(expression, nameof(expression));

            //
            // NB: We don't check here for an accessible setter in order to support anonymous types where
            //     the getter is specified instead.
            //

            if (!memberType.IsAssignableFrom(expression.Type))
            {
                throw LinqError.ArgumentTypesMustMatch();
            }

            if (member.DeclaringType == null)
            {
                throw Error.NotAMemberOfAnyType(member);
            }

            ValidateType(member.DeclaringType);

            return(new MemberInitializer(member, expression));
        }
        /// <summary>
        /// Creates an expression representing an indexer access operation.
        /// </summary>
        /// <param name="object">The object to access.</param>
        /// <param name="argument">The argument that will be used to index or slice the object.</param>
        /// <param name="lengthOrCount">The property used to retrieve the element count of the object getting accessed.</param>
        /// <param name="indexOrSlice">The member used to index or slice the object.</param>
        /// <returns>A new <see cref="IndexerAccessCSharpExpression"/> instance representing the array access operation.</returns>
        public static IndexerAccessCSharpExpression IndexerAccess(Expression @object, Expression argument, PropertyInfo lengthOrCount, MemberInfo indexOrSlice)
        {
            RequiresCanRead(@object, nameof(@object));

            //
            // The argument can be of type Index or Range. We'll check indexOrSlice accordingly below.
            //

            RequiresCanRead(argument, nameof(argument));

            if (argument.Type != typeof(Index) && argument.Type != typeof(Range))
            {
                throw Error.InvalidIndexerAccessArgumentType(argument.Type);
            }

            //
            // A type is Countable if it has a property named Length or Count with an accessible getter and a return type of int.
            //

            lengthOrCount ??= FindCountProperty("Length") ?? FindCountProperty("Count");

            PropertyInfo FindCountProperty(string name) => @object.Type.GetProperty(name, BindingFlags.Public | BindingFlags.Instance, binder: null, typeof(int), Type.EmptyTypes, modifiers: null);

            ContractUtils.RequiresNotNull(lengthOrCount, nameof(lengthOrCount));

            var lengthOrCountGetMethod = lengthOrCount.GetGetMethod(nonPublic: true); // NB: System.Linq.Expressions allows non-public properties.

            if (lengthOrCountGetMethod == null)
            {
                throw LinqError.PropertyDoesNotHaveAccessor(lengthOrCount);
            }

            if (lengthOrCountGetMethod.IsStatic)
            {
                throw Error.AccessorCannotBeStatic(lengthOrCountGetMethod);
            }

            if (lengthOrCountGetMethod.GetParametersCached().Length != 0)
            {
                throw LinqError.IncorrectNumberOfMethodCallArguments(lengthOrCountGetMethod);
            }

            if (!TypeUtils.IsValidInstanceType(lengthOrCount, @object.Type))
            {
                throw LinqError.PropertyNotDefinedForType(lengthOrCount, @object.Type);
            }

            if (lengthOrCount.PropertyType != typeof(int))
            {
                throw Error.InvalidLengthOrCountPropertyType(lengthOrCount);
            }

            ValidateMethodInfo(lengthOrCountGetMethod);

            if (argument.Type == typeof(Index))
            {
                //
                // The type has an accessible instance indexer which takes a single int as the argument.
                //

                indexOrSlice ??= FindIndexer();

                PropertyInfo FindIndexer()
                {
                    var indexers = (from p in @object.Type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                    let i = p.GetIndexParameters()
                                            where i.Length == 1 && i[0].ParameterType == typeof(int)
                                            select p)
                                   .ToArray();

                    return(indexers.Length == 1 ? indexers[0] : null);
                }

                ContractUtils.RequiresNotNull(indexOrSlice, nameof(indexOrSlice));

                var index = indexOrSlice as PropertyInfo ?? GetProperty(indexOrSlice as MethodInfo ?? throw Error.InvalidIndexMember(indexOrSlice));

                indexOrSlice = index;                                    // NB: Store the property rather than a method.

                var indexAccessor = index.GetGetMethod(nonPublic: true); // NB: System.Linq.Expressions allows non-public properties.

                if (indexAccessor == null)
                {
                    indexAccessor = index.GetSetMethod(nonPublic: true) ?? throw LinqError.PropertyDoesNotHaveAccessor(indexOrSlice);

                    if (indexAccessor.GetParametersCached().Length != 2)
                    {
                        throw LinqError.IncorrectNumberOfMethodCallArguments(indexAccessor);
                    }
                }
                else if (indexAccessor.GetParametersCached().Length != 1)
                {
                    throw LinqError.IncorrectNumberOfMethodCallArguments(indexAccessor);
                }

                if (indexAccessor.IsStatic)
                {
                    throw Error.AccessorCannotBeStatic(indexAccessor);
                }

                if (!TypeUtils.IsValidInstanceType(indexAccessor, @object.Type))
                {
                    throw LinqError.PropertyNotDefinedForType(indexAccessor, @object.Type);
                }

                if (indexAccessor.GetParametersCached()[0].ParameterType != typeof(int))
                {
                    throw Error.InvalidIndexerParameterType(indexOrSlice);
                }

                ValidateMethodInfo(indexAccessor);
            }
            else
            {
                //
                // The type has an accessible member named Slice which has two parameters of type int.
                //

                Debug.Assert(argument.Type == typeof(Range));

                indexOrSlice ??= FindSliceMethod();

                MethodInfo FindSliceMethod() => @object.Type.GetMethod(@object.Type == typeof(string) ? "Substring" : "Slice", BindingFlags.Public | BindingFlags.Instance, binder: null, new[] { typeof(int), typeof(int) }, modifiers: null);

                ContractUtils.RequiresNotNull(indexOrSlice, nameof(indexOrSlice));

                var slice = indexOrSlice as MethodInfo ?? throw Error.InvalidSliceMember(indexOrSlice);

                ValidateMethodInfo(slice);

                if (slice.IsStatic)
                {
                    throw Error.SliceMethodMustNotBeStatic(slice);
                }

                ValidateCallInstanceType(@object.Type, slice);

                var sliceParams = slice.GetParametersCached();

                if (sliceParams.Length != 2 || sliceParams[0].ParameterType != typeof(int) || sliceParams[1].ParameterType != typeof(int))
                {
                    throw Error.InvalidSliceParameters(slice);
                }
            }

            return(new IndexerAccessCSharpExpression(@object, argument, lengthOrCount, indexOrSlice));
        }