// 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);
}
}