Esempio n. 1
0
        /// <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));
        }