117
throw ParseError(errorPos, Res.CannotConvertValue,
GetTypeName(exprType), GetTypeName(type));
}
Expression ParseMemberAccess(Type type, Expression instance) {
if (instance != null) type = instance.Type;
int errorPos = token.pos;
string id = GetIdentifier();
NextToken();
if (token.id == TokenId.OpenParen) {
if (instance != null && type != typeof(string)) {
Type enumerableType = FindGenericType(typeof(IEnumerable<>), type);
if (enumerableType != null) {
Type elementType = enumerableType.GetGenericArguments()[0];
return ParseAggregate(instance, elementType, id, errorPos);
}
}
Expression[] args = ParseArgumentList();
MethodBase mb;
switch (FindMethod(type, id, instance == null, args, out mb)) {
case 0:
throw ParseError(errorPos, Res.NoApplicableMethod,
id, GetTypeName(type));
case 1:
MethodInfo method = (MethodInfo)mb;
if (!IsPredefinedType(method.DeclaringType))
throw ParseError(errorPos, Res.MethodsAreInaccessible,
GetTypeName(method.DeclaringType));
if (method.ReturnType == typeof(void))
throw ParseError(errorPos, Res.MethodIsVoid,
id, GetTypeName(method.DeclaringType));
return Expression.Call(instance, (MethodInfo)method, args);
default:
throw ParseError(errorPos, Res.AmbiguousMethodInvocation,
id, GetTypeName(type));
}
}
else {
MemberInfo member = FindPropertyOrField(type, id, instance == null);
if (member == null)
throw ParseError(errorPos, Res.UnknownPropertyOrField,
id, GetTypeName(type));
return member is PropertyInfo ?
Expression.Property(instance, (PropertyInfo)member) :
Expression.Field(instance, (FieldInfo)member);
}
}
static Type FindGenericType(Type generic, Type type) {
while (type != null && type != typeof(object)) {
if (type.IsGenericType && type.GetGenericTypeDefinition() == generic) return type;
if (generic.IsInterface) {
foreach (Type intfType in type.GetInterfaces()) {
Type found = FindGenericType(generic, intfType);
if (found != null) return found;
}
}