private static IEnumerable <SPFieldAttribute> EnumerateFieldAttributes(SPModelDescriptor descriptor, Type sourceType, Type implementedType) { InterfaceMapping mapping = default(InterfaceMapping); if (sourceType.IsInterface) { mapping = implementedType.GetInterfaceMap(sourceType); } foreach (MemberInfo member in sourceType.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { SPModelFieldAssociationCollection collection = QueryableFields.EnsureKeyValue(member); SPModelFieldAssociationCollection otherCollection = null; if (sourceType.IsInterface) { MethodInfo lookupMethod = null; if (member.MemberType == MemberTypes.Property) { lookupMethod = ((PropertyInfo)member).GetGetMethod() ?? ((PropertyInfo)member).GetSetMethod(); } else if (member.MemberType == MemberTypes.Method) { lookupMethod = (MethodInfo)member; } if (lookupMethod != null) { int pos = Array.IndexOf(mapping.InterfaceMethods, lookupMethod); if (pos >= 0) { MemberInfo mappedMember = mapping.TargetMethods[pos]; if (member.MemberType == MemberTypes.Property) { mappedMember = implementedType.GetProperty(mappedMember.Name.Substring(4)); } if (mappedMember != null) { otherCollection = QueryableFields.EnsureKeyValue(mappedMember); if (otherCollection.Count > 0) { foreach (SPModelFieldAssociation value in otherCollection) { collection.Add(value); } } } } } } SPFieldProvisionMode provisionMode = SPFieldProvisionMode.Default; SPModelFieldAssociationCollection basePropertyCollection = null; IEnumerable <SPFieldAttribute> attributes = member.GetCustomAttributes <SPFieldAttribute>(true); if (member.MemberType == MemberTypes.Property) { PropertyInfo baseProperty = ((PropertyInfo)member).GetBaseDefinition(); if (baseProperty != member) { if (!attributes.Any()) { attributes = baseProperty.GetCustomAttributes <SPFieldAttribute>(false); provisionMode = SPFieldProvisionMode.None; } else { basePropertyCollection = QueryableFields.EnsureKeyValue(baseProperty); provisionMode = SPFieldProvisionMode.FieldLink; } } } if (member.DeclaringType != sourceType) { provisionMode = SPFieldProvisionMode.FieldLink; } foreach (SPFieldAttribute attribute in attributes) { if (attribute.IncludeInQuery) { PropertyInfo property = null; SPModelQueryPropertyAttribute queryPropertyAttribute = member.GetCustomAttribute <SPModelQueryPropertyAttribute>(false); if (queryPropertyAttribute != null) { property = queryPropertyAttribute.QueryProperty; } SPModelFieldAssociation value = new SPModelFieldAssociation(descriptor, attribute, property); collection.Add(value); if (otherCollection != null) { otherCollection.Add(value); } if (basePropertyCollection != null) { basePropertyCollection.Add(value); } if (property != null) { SPModelFieldAssociationCollection foreignPropertyCollection = QueryableFields.EnsureKeyValue(property); foreignPropertyCollection.Add(new SPModelFieldAssociation(descriptor, attribute, null)); } } yield return(attribute.Clone(provisionMode)); } } }
protected override Expression VisitMemberAccess(MemberExpression expression) { SPModelQueryExpressionScope currentScope = stack.Peek(); switch (expression.Expression.NodeType) { case ExpressionType.Parameter: case ExpressionType.MemberAccess: case ExpressionType.Convert: case ExpressionType.Call: if (expression.Member.DeclaringType == typeof(ISPModelMetaData)) { switch (expression.Member.Name) { case "ID": currentScope.Field = SPModelQueryFieldInfo.ID; break; case "UniqueId": currentScope.Field = SPModelQueryFieldInfo.UniqueId; break; case "FileRef": currentScope.Field = SPModelQueryFieldInfo.FileRef; break; case "FileLeafRef": currentScope.Field = SPModelQueryFieldInfo.FileLeafRef; break; case "LastModified": currentScope.Field = SPModelQueryFieldInfo.LastModified; break; case "CheckOutUserID": currentScope.Field = SPModelQueryFieldInfo.CheckOutUserID; break; default: throw new NotSupportedException(String.Format("The member '{0}' is not supported", expression.Member.Name)); } } else if (expression.Member.DeclaringType == typeof(TaxonomyItem) || expression.Member.DeclaringType == typeof(SPPrincipal)) { switch (expression.Member.Name) { case "Id": case "ID": Visit(expression.Expression); break; default: throw new NotSupportedException(String.Format("The member '{0}' is not supported", expression.Member.Name)); } } else { currentScope.MemberType = expression.Type; currentScope.Member = expression.Member; currentScope.FieldAssociations = SPModelFieldAssociationCollection.GetByMember(expression.Member); } break; default: throw new NotSupportedException(String.Format("The member '{0}' is not supported", expression.Member.Name)); } return(expression); }
protected override Expression VisitMemberAccess(MemberExpression expression) { if (invariantExpression) { return(base.VisitMemberAccess(expression)); } if (expression.Expression != lambdaParam) { if (expression.Member.DeclaringType == typeof(ISPModelMetaData) && ((expression.Expression.NodeType == ExpressionType.Call && ((MethodCallExpression)expression.Expression).Method == typeof(SPModelExtension).GetMethod("GetMetaData") && ((MethodCallExpression)expression.Expression).Arguments[0] == lambdaParam) || (expression.Expression.NodeType == ExpressionType.Convert && ((UnaryExpression)expression.Expression).Operand == lambdaParam))) { // allow non-direct field access on the ISPModelMetaData interface } else { Expression result = base.VisitMemberAccess(expression); if (expression.Member.DeclaringType.IsGenericType && expression.Member.DeclaringType.GetGenericTypeDefinition() == typeof(Nullable <>) && expression.Member.Name == "HasValue") { CamlExpression expr = currentScope.GetExpression(v => Caml.IsNotNull(v.FieldRef)); currentScope.Reset(); currentScope.Expression = expr; } return(result); } } currentScope.MemberType = expression.Type; currentScope.Member = expression.Member; currentScope.Field = default(SPModelQueryFieldInfo); currentScope.FieldAssociations = null; if (expression.Member.DeclaringType == typeof(ISPModelMetaData)) { switch (expression.Member.Name) { case "ID": currentScope.Field = SPModelQueryFieldInfo.ID; break; case "UniqueId": currentScope.Field = SPModelQueryFieldInfo.UniqueId; break; case "FileRef": currentScope.Field = SPModelQueryFieldInfo.FileRef; break; case "FileLeafRef": currentScope.Field = SPModelQueryFieldInfo.FileLeafRef; break; case "LastModified": currentScope.Field = SPModelQueryFieldInfo.LastModified; break; case "CheckOutUserID": currentScope.Field = SPModelQueryFieldInfo.CheckOutUserID; break; default: throw new NotSupportedException(String.Format("Member '{0}' is not supported", GetMemberFullName(expression.Member))); } } else { currentScope.FieldAssociations = SPModelFieldAssociationCollection.GetByMember(expression.Member); foreach (SPFieldAttribute field in currentScope.FieldAssociations.Fields) { if (field.TypeAsString == "TaxonomyFieldType" || field.TypeAsString == "TaxonomyFieldTypeMulti") { builder.TaxonomyFields.Add(field.ListFieldInternalName); } } } if (builder.SelectExpression != null) { if (currentScope.Field.FieldRef != null) { builder.AddSelectProperty(currentScope.Field.FieldRef); } else if (currentScope.FieldAssociations.Queryable && expression.Member.MemberType == MemberTypes.Property && ((PropertyInfo)expression.Member).GetGetMethod().IsAbstract) { builder.AddSelectProperty(currentScope.FieldAssociations.Fields.First().ListFieldInternalName); } else { builder.SelectAllProperties = true; } } return(expression); }