/// <summary> /// Returns the list of key properties defined on <paramref name="type"/>; null if <paramref name="type"/> is complex. /// </summary> /// <param name="type">Type in question.</param> /// <param name="hasProperties">true if <paramref name="type"/> has any (declared or inherited) properties; otherwise false.</param> /// <returns>Returns the list of key properties defined on <paramref name="type"/>; null if <paramref name="type"/> is complex.</returns> internal static PropertyInfo[] GetKeyPropertiesOnType(Type type, out bool hasProperties) { if (CommonUtil.IsUnsupportedType(type)) { throw new InvalidOperationException(c.Strings.ClientType_UnsupportedType(type)); } string typeName = type.ToString(); IEnumerable <object> customAttributes = type.GetCustomAttributes(true); bool isEntity = customAttributes.OfType <EntityTypeAttribute>().Any(); KeyAttribute dataServiceKeyAttribute = customAttributes.OfType <KeyAttribute>().FirstOrDefault(); List <PropertyInfo> keyProperties = new List <PropertyInfo>(); PropertyInfo[] properties = ClientTypeUtil.GetPropertiesOnType(type, false /*declaredOnly*/).ToArray(); hasProperties = properties.Length > 0; KeyKind currentKeyKind = KeyKind.NotKey; KeyKind newKeyKind = KeyKind.NotKey; foreach (PropertyInfo propertyInfo in properties) { if ((newKeyKind = ClientTypeUtil.IsKeyProperty(propertyInfo, dataServiceKeyAttribute)) != KeyKind.NotKey) { if (newKeyKind > currentKeyKind) { keyProperties.Clear(); currentKeyKind = newKeyKind; keyProperties.Add(propertyInfo); } else if (newKeyKind == currentKeyKind) { keyProperties.Add(propertyInfo); } } } Type keyPropertyDeclaringType = null; foreach (PropertyInfo key in keyProperties) { if (keyPropertyDeclaringType == null) { keyPropertyDeclaringType = key.DeclaringType; } else if (keyPropertyDeclaringType != key.DeclaringType) { throw c.Error.InvalidOperation(c.Strings.ClientType_KeysOnDifferentDeclaredType(typeName)); } if (!PrimitiveType.IsKnownType(key.PropertyType) && !(key.PropertyType.GetGenericTypeDefinition() == typeof(System.Nullable <>) && key.PropertyType.GetGenericArguments().First().IsEnum())) { throw c.Error.InvalidOperation(c.Strings.ClientType_KeysMustBeSimpleTypes(key.Name, typeName, key.PropertyType.FullName)); } } if (dataServiceKeyAttribute != null) { if (newKeyKind == KeyKind.AttributedKey && keyProperties.Count != dataServiceKeyAttribute?.KeyNames.Count) { var m = (from string a in dataServiceKeyAttribute.KeyNames where (from b in properties where b.Name == a select b).FirstOrDefault() == null select a).First <string>(); throw c.Error.InvalidOperation(c.Strings.ClientType_MissingProperty(typeName, m)); } } return(keyProperties.Count > 0 ? keyProperties.ToArray() : (isEntity ? ClientTypeUtil.EmptyPropertyInfoArray : null)); }