public void Ctor()
        {
            var mt = new MimeTypeAttribute("member", "type");

            Assert.AreEqual("member", mt.MemberName);
            Assert.AreEqual("type", mt.MimeType);
        }
Beispiel #2
0
        private static void BuildTypeProperties(ResourceType parentResourceType, IDictionary <Type, ResourceType> knownTypes, IDictionary <ResourceType, List <ResourceType> > childTypes, Queue <ResourceType> unvisitedTypes, IEnumerable <ResourceSet> entitySets)
        {
            BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance;

            if (parentResourceType.BaseType != null)
            {
                bindingFlags |= BindingFlags.DeclaredOnly;
            }
            HashSet <string> set    = new HashSet <string>(IgnorePropertiesAttribute.GetProperties(parentResourceType.InstanceType, false, bindingFlags), StringComparer.Ordinal);
            HashSet <string> source = new HashSet <string>(LoadETagProperties(parentResourceType), StringComparer.Ordinal);
            ResourceKeyKind  kind   = (ResourceKeyKind)0x7fffffff;

            PropertyInfo[] properties = parentResourceType.InstanceType.GetProperties(bindingFlags);
            if (!properties.Any <PropertyInfo>() && (parentResourceType.BaseType == null))
            {
                throw new NotSupportedException(System.Data.Services.Strings.ReflectionProvider_ResourceTypeHasNoPublicallyVisibleProperties(parentResourceType.FullName));
            }
            foreach (PropertyInfo info in properties)
            {
                if (!set.Contains(info.Name))
                {
                    ResourceType collectionResourceType;
                    if (!info.CanRead || (info.GetIndexParameters().Length != 0))
                    {
                        throw new InvalidOperationException(System.Data.Services.Strings.ReflectionProvider_InvalidProperty(info.Name, parentResourceType.FullName));
                    }
                    ResourcePropertyKind collection = (ResourcePropertyKind)(-1);
                    Type propertyType = info.PropertyType;
                    bool flag         = false;
                    if (!BaseServiceProvider.TryGetType(knownTypes, propertyType, out collectionResourceType))
                    {
                        Type iEnumerableElement = BaseServiceProvider.GetIEnumerableElement(info.PropertyType);
                        if (iEnumerableElement != null)
                        {
                            BaseServiceProvider.TryGetType(knownTypes, iEnumerableElement, out collectionResourceType);
                            flag         = true;
                            propertyType = iEnumerableElement;
                        }
                    }
                    if (collectionResourceType != null)
                    {
                        if (collectionResourceType.ResourceTypeKind == ResourceTypeKind.Primitive)
                        {
                            if (flag)
                            {
                                collection = ResourcePropertyKind.Collection;
                            }
                            else
                            {
                                ResourceKeyKind kind3;
                                if (((parentResourceType.BaseType == null) && (parentResourceType.ResourceTypeKind == ResourceTypeKind.EntityType)) && IsPropertyKeyProperty(info, out kind3))
                                {
                                    if (kind3 < kind)
                                    {
                                        if (parentResourceType.KeyProperties.Count != 0)
                                        {
                                            parentResourceType.RemoveKeyProperties();
                                        }
                                        kind       = kind3;
                                        collection = ResourcePropertyKind.Key | ResourcePropertyKind.Primitive;
                                    }
                                    else if (kind3 == kind)
                                    {
                                        collection = ResourcePropertyKind.Key | ResourcePropertyKind.Primitive;
                                    }
                                    else
                                    {
                                        collection = ResourcePropertyKind.Primitive;
                                    }
                                }
                                else
                                {
                                    collection = ResourcePropertyKind.Primitive;
                                }
                            }
                        }
                        else if (collectionResourceType.ResourceTypeKind == ResourceTypeKind.ComplexType)
                        {
                            collection = flag ? ResourcePropertyKind.Collection : ResourcePropertyKind.ComplexType;
                        }
                        else if (collectionResourceType.ResourceTypeKind == ResourceTypeKind.EntityType)
                        {
                            collection = flag ? ResourcePropertyKind.ResourceSetReference : ResourcePropertyKind.ResourceReference;
                        }
                    }
                    else
                    {
                        collectionResourceType = IsEntityOrComplexType(propertyType, knownTypes, childTypes, unvisitedTypes);
                        if (collectionResourceType != null)
                        {
                            if (collectionResourceType.ResourceTypeKind == ResourceTypeKind.ComplexType)
                            {
                                if (flag)
                                {
                                    if (BaseServiceProvider.GetIEnumerableElement(propertyType) != null)
                                    {
                                        throw new InvalidOperationException(System.Data.Services.Strings.ReflectionProvider_CollectionOfCollectionProperty(info.Name, parentResourceType.FullName));
                                    }
                                    collection = ResourcePropertyKind.Collection;
                                }
                                else
                                {
                                    collection = ResourcePropertyKind.ComplexType;
                                }
                            }
                            else
                            {
                                collection = flag ? ResourcePropertyKind.ResourceSetReference : ResourcePropertyKind.ResourceReference;
                            }
                        }
                    }
                    if ((collectionResourceType == null) || ((collectionResourceType.ResourceTypeKind == ResourceTypeKind.EntityType) && (parentResourceType.ResourceTypeKind == ResourceTypeKind.ComplexType)))
                    {
                        if (collectionResourceType != null)
                        {
                            throw new InvalidOperationException(System.Data.Services.Strings.ReflectionProvider_ComplexTypeWithNavigationProperty(info.Name, parentResourceType.FullName));
                        }
                        if (flag && (BaseServiceProvider.GetIEnumerableElement(propertyType) != null))
                        {
                            throw new InvalidOperationException(System.Data.Services.Strings.ReflectionProvider_CollectionOfCollectionProperty(info.Name, parentResourceType.FullName));
                        }
                        if (flag)
                        {
                            throw new InvalidOperationException(System.Data.Services.Strings.ReflectionProvider_CollectionOfUnsupportedTypeProperty(info.Name, parentResourceType.FullName, propertyType));
                        }
                        if (CommonUtil.IsUnsupportedType(propertyType))
                        {
                            throw new InvalidOperationException(System.Data.Services.Strings.BadProvider_UnsupportedPropertyType(info.Name, parentResourceType.FullName));
                        }
                        throw new InvalidOperationException(System.Data.Services.Strings.ReflectionProvider_InvalidProperty(info.Name, parentResourceType.FullName));
                    }
                    if ((collectionResourceType.ResourceTypeKind == ResourceTypeKind.EntityType) && (InternalGetContainerForResourceType(propertyType, entitySets) == null))
                    {
                        throw new InvalidOperationException(System.Data.Services.Strings.ReflectionProvider_EntityPropertyWithNoEntitySet(parentResourceType.FullName, info.Name));
                    }
                    if (collection == ResourcePropertyKind.Collection)
                    {
                        collectionResourceType = ResourceType.GetCollectionResourceType(collectionResourceType);
                    }
                    if (source.Remove(info.Name))
                    {
                        collection |= ResourcePropertyKind.ETag;
                    }
                    ResourceProperty  property          = new ResourceProperty(info.Name, collection, collectionResourceType);
                    MimeTypeAttribute mimeTypeAttribute = MimeTypeAttribute.GetMimeTypeAttribute(info);
                    if (mimeTypeAttribute != null)
                    {
                        property.MimeType = mimeTypeAttribute.MimeType;
                    }
                    parentResourceType.AddProperty(property);
                }
            }
            if ((parentResourceType.ResourceTypeKind == ResourceTypeKind.EntityType) && ((parentResourceType.KeyProperties == null) || (parentResourceType.KeyProperties.Count == 0)))
            {
                throw new InvalidOperationException(System.Data.Services.Strings.ReflectionProvider_KeyPropertiesCannotBeIgnored(parentResourceType.FullName));
            }
            if (source.Count != 0)
            {
                throw new InvalidOperationException(System.Data.Services.Strings.ReflectionProvider_ETagPropertyNameNotValid(source.ElementAt <string>(0), parentResourceType.FullName));
            }
        }
		public void Ctor()
		{
			var mt = new MimeTypeAttribute ("member", "type");
			Assert.AreEqual ("member", mt.MemberName);
			Assert.AreEqual ("type", mt.MimeType);
		}
        /// <summary>
        /// Adds a new <see cref="ServiceOperation"/> based on the specified <paramref name="method"/>
        /// instance.
        /// </summary>
        /// <param name="method">Method to expose as a service operation.</param>
        /// <param name="protocolMethod">Protocol (for example HTTP) method the service operation responds to.</param>
        private void AddServiceOperation(MethodInfo method, string protocolMethod)
        {
            Debug.Assert(method != null, "method != null");
            Debug.Assert(!method.IsAbstract, "!method.IsAbstract - if method is abstract, the type is abstract - already checked");

            // This method is only called for V1 providers, since in case of custom providers,
            // they are suppose to load the metadata themselves.
            if (this.metadata.ServiceOperations.ContainsKey(method.Name))
            {
                throw new InvalidOperationException(Strings.BaseServiceProvider_OverloadingNotSupported(this.Type, method));
            }

            bool hasSingleResult = SingleResultAttribute.MethodHasSingleResult(method);
            ServiceOperationResultKind resultKind;
            ResourceType resourceType = null;

            if (method.ReturnType == typeof(void))
            {
                resultKind = ServiceOperationResultKind.Void;
                this.UpdateEdmSchemaVersion(MetadataEdmSchemaVersion.Version1Dot1);
            }
            else
            {
                // Load the metadata of the resource type on the fly.
                // For Edm provider, it might not mean anything, but for reflection service provider, we need to
                // load the metadata of the type if its used only in service operation case
                Type resultType = null;
                if (WebUtil.IsPrimitiveType(method.ReturnType))
                {
                    resultKind   = ServiceOperationResultKind.DirectValue;
                    resultType   = method.ReturnType;
                    resourceType = ResourceType.GetPrimitiveResourceType(resultType);
                }
                else
                {
                    Type queryableElement = GetGenericInterfaceElementType(method.ReturnType, IQueryableTypeFilter);
                    if (queryableElement != null)
                    {
                        resultKind = hasSingleResult ?
                                     ServiceOperationResultKind.QueryWithSingleResult :
                                     ServiceOperationResultKind.QueryWithMultipleResults;
                        resultType = queryableElement;
                    }
                    else
                    {
                        Type enumerableElement = GetIEnumerableElement(method.ReturnType);
                        if (enumerableElement != null)
                        {
                            resultKind = ServiceOperationResultKind.Enumeration;
                            resultType = enumerableElement;
                        }
                        else
                        {
                            resultType = method.ReturnType;
                            resultKind = ServiceOperationResultKind.DirectValue;
                            this.UpdateEdmSchemaVersion(MetadataEdmSchemaVersion.Version1Dot1);
                        }
                    }

                    Debug.Assert(resultType != null, "resultType != null");
                    resourceType = ResourceType.GetPrimitiveResourceType(resultType);
                    if (resourceType == null)
                    {
                        resourceType = this.PopulateMetadataForType(resultType, this.TypeCache, this.ChildTypesCache, this.EntitySets.Values);
                    }
                }

                if (resourceType == null)
                {
                    throw new InvalidOperationException(Strings.BaseServiceProvider_UnsupportedReturnType(method, method.ReturnType));
                }

                if (resultKind == ServiceOperationResultKind.Enumeration && hasSingleResult)
                {
                    throw new InvalidOperationException(Strings.BaseServiceProvider_IEnumerableAlwaysMultiple(this.Type, method));
                }

                if (hasSingleResult ||
                    (!hasSingleResult &&
                     (resourceType.ResourceTypeKind == ResourceTypeKind.ComplexType ||
                      resourceType.ResourceTypeKind == ResourceTypeKind.Primitive)))
                {
                    this.UpdateEdmSchemaVersion(MetadataEdmSchemaVersion.Version1Dot1);
                }
            }

            ParameterInfo[]             parametersInfo = method.GetParameters();
            ServiceOperationParameter[] parameters     = new ServiceOperationParameter[parametersInfo.Length];
            for (int i = 0; i < parameters.Length; i++)
            {
                ParameterInfo parameterInfo = parametersInfo[i];
                if (parameterInfo.IsOut || parameterInfo.IsRetval)
                {
                    throw new InvalidOperationException(Strings.BaseServiceProvider_ParameterNotIn(method, parameterInfo));
                }

                ResourceType parameterType = ResourceType.GetPrimitiveResourceType(parameterInfo.ParameterType);
                if (parameterType == null)
                {
                    throw new InvalidOperationException(
                              Strings.BaseServiceProvider_ParameterTypeNotSupported(method, parameterInfo, parameterInfo.ParameterType));
                }

                string parameterName = parameterInfo.Name ?? "p" + i.ToString(CultureInfo.InvariantCulture);
                parameters[i] = new ServiceOperationParameter(parameterName, parameterType);
            }

            ResourceSet container = null;

            if (resourceType != null && resourceType.ResourceTypeKind == ResourceTypeKind.EntityType)
            {
                if (!this.TryFindAnyContainerForType(resourceType, out container))
                {
                    throw new InvalidOperationException(
                              Strings.BaseServiceProvider_ServiceOperationMissingSingleEntitySet(method, resourceType.FullName));
                }
            }

            ServiceOperation operation = new ServiceOperation(method.Name, resultKind, resourceType, container, protocolMethod, parameters);

            operation.CustomState = method;
            MimeTypeAttribute attribute = MimeTypeAttribute.GetMimeTypeAttribute(method);

            if (attribute != null)
            {
                operation.MimeType = attribute.MimeType;
            }

            this.metadata.ServiceOperations.Add(method.Name, operation);
        }
        private void AddServiceOperation(MethodInfo method, string protocolMethod)
        {
            ServiceOperationResultKind @void;

            if (this.metadata.ServiceOperations.ContainsKey(method.Name))
            {
                throw new InvalidOperationException(System.Data.Services.Strings.BaseServiceProvider_OverloadingNotSupported(this.Type, method));
            }
            bool         flag      = SingleResultAttribute.MethodHasSingleResult(method);
            ResourceType primitive = null;

            if (method.ReturnType == typeof(void))
            {
                @void = ServiceOperationResultKind.Void;
            }
            else
            {
                System.Type returnType;
                if (WebUtil.IsPrimitiveType(method.ReturnType))
                {
                    @void      = ServiceOperationResultKind.DirectValue;
                    returnType = method.ReturnType;
                    primitive  = ResourceType.PrimitiveResourceTypeMap.GetPrimitive(returnType);
                }
                else
                {
                    System.Type genericInterfaceElementType = GetGenericInterfaceElementType(method.ReturnType, new TypeFilter(BaseServiceProvider.IQueryableTypeFilter));
                    if (genericInterfaceElementType != null)
                    {
                        @void      = flag ? ServiceOperationResultKind.QueryWithSingleResult : ServiceOperationResultKind.QueryWithMultipleResults;
                        returnType = genericInterfaceElementType;
                    }
                    else
                    {
                        System.Type iEnumerableElement = GetIEnumerableElement(method.ReturnType);
                        if (iEnumerableElement != null)
                        {
                            @void      = ServiceOperationResultKind.Enumeration;
                            returnType = iEnumerableElement;
                        }
                        else
                        {
                            returnType = method.ReturnType;
                            @void      = ServiceOperationResultKind.DirectValue;
                        }
                    }
                    primitive = ResourceType.PrimitiveResourceTypeMap.GetPrimitive(returnType);
                    if (primitive == null)
                    {
                        primitive = this.PopulateMetadataForType(returnType, this.TypeCache, this.ChildTypesCache, this.EntitySets.Values);
                    }
                }
                if (primitive == null)
                {
                    throw new InvalidOperationException(System.Data.Services.Strings.BaseServiceProvider_UnsupportedReturnType(method, method.ReturnType));
                }
                if ((@void == ServiceOperationResultKind.Enumeration) && flag)
                {
                    throw new InvalidOperationException(System.Data.Services.Strings.BaseServiceProvider_IEnumerableAlwaysMultiple(this.Type, method));
                }
            }
            ParameterInfo[]             parameters     = method.GetParameters();
            ServiceOperationParameter[] parameterArray = new ServiceOperationParameter[parameters.Length];
            for (int i = 0; i < parameterArray.Length; i++)
            {
                ParameterInfo info = parameters[i];
                if (info.IsOut || info.IsRetval)
                {
                    throw new InvalidOperationException(System.Data.Services.Strings.BaseServiceProvider_ParameterNotIn(method, info));
                }
                ResourceType parameterType = ResourceType.PrimitiveResourceTypeMap.GetPrimitive(info.ParameterType);
                if (parameterType == null)
                {
                    throw new InvalidOperationException(System.Data.Services.Strings.BaseServiceProvider_ParameterTypeNotSupported(method, info, info.ParameterType));
                }
                string name = info.Name ?? ("p" + i.ToString(CultureInfo.InvariantCulture));
                parameterArray[i] = new ServiceOperationParameter(name, parameterType);
            }
            ResourceSet container = null;

            if (((primitive != null) && (primitive.ResourceTypeKind == ResourceTypeKind.EntityType)) && !this.TryFindAnyContainerForType(primitive, out container))
            {
                throw new InvalidOperationException(System.Data.Services.Strings.BaseServiceProvider_ServiceOperationMissingSingleEntitySet(method, primitive.FullName));
            }
            ServiceOperation operation = new ServiceOperation(method.Name, @void, primitive, container, protocolMethod, parameterArray)
            {
                CustomState = method
            };
            MimeTypeAttribute mimeTypeAttribute = MimeTypeAttribute.GetMimeTypeAttribute(method);

            if (mimeTypeAttribute != null)
            {
                operation.MimeType = mimeTypeAttribute.MimeType;
            }
            this.metadata.ServiceOperations.Add(method.Name, operation);
        }
        /// <summary>
        /// Returns a new <see cref="ServiceOperation"/> based on the specified <paramref name="method"/>
        /// instance.
        /// </summary>
        /// <param name="method">Method to expose as a service operation.</param>
        /// <param name="protocolMethod">Protocol (for example HTTP) method the service operation responds to.</param>
        /// <returns>Service operation corresponding to give <paramref name="method"/>.</returns>
        private ServiceOperation GetServiceOperationForMethod(MethodInfo method, string protocolMethod)
        {
            Debug.Assert(method != null, "method != null");
            Debug.Assert(!method.IsAbstract, "!method.IsAbstract - if method is abstract, the type is abstract - already checked");

            bool hasSingleResult = BaseServiceProvider.MethodHasSingleResult(method);
            ServiceOperationResultKind resultKind;
            ResourceType resourceType = null;

            if (method.ReturnType == typeof(void))
            {
                resultKind = ServiceOperationResultKind.Void;
            }
            else
            {
                // Load the metadata of the resource type on the fly.
                // For Edm provider, it might not mean anything, but for reflection service provider, we need to
                // load the metadata of the type if its used only in service operation case
                Type resultType;
                if (WebUtil.IsPrimitiveType(method.ReturnType))
                {
                    resultKind   = ServiceOperationResultKind.DirectValue;
                    resultType   = method.ReturnType;
                    resourceType = PrimitiveResourceTypeMap.TypeMap.GetPrimitive(resultType);
                }
                else
                {
                    Type queryableElement = BaseServiceProvider.GetIQueryableElement(method.ReturnType);
                    if (queryableElement != null)
                    {
                        resultKind = hasSingleResult ?
                                     ServiceOperationResultKind.QueryWithSingleResult :
                                     ServiceOperationResultKind.QueryWithMultipleResults;
                        resultType = queryableElement;
                    }
                    else
                    {
                        Type enumerableElement = BaseServiceProvider.GetIEnumerableElement(method.ReturnType);
                        if (enumerableElement != null)
                        {
                            resultKind = ServiceOperationResultKind.Enumeration;
                            resultType = enumerableElement;
                        }
                        else
                        {
                            resultType = method.ReturnType;
                            resultKind = ServiceOperationResultKind.DirectValue;
                        }
                    }

                    Debug.Assert(resultType != null, "resultType != null");
                    resourceType = PrimitiveResourceTypeMap.TypeMap.GetPrimitive(resultType);
                    if (resourceType == null)
                    {
                        resourceType = this.ResolveResourceType(resultType);
                    }
                }

                if (resourceType == null)
                {
                    throw new InvalidOperationException(Strings.BaseServiceProvider_UnsupportedReturnType(method, method.ReturnType));
                }

                if (resultKind == ServiceOperationResultKind.Enumeration && hasSingleResult)
                {
                    throw new InvalidOperationException(Strings.BaseServiceProvider_IEnumerableAlwaysMultiple(type, method));
                }
            }

            ParameterInfo[]             parametersInfo = method.GetParameters();
            ServiceOperationParameter[] parameters     = new ServiceOperationParameter[parametersInfo.Length];
            for (int i = 0; i < parameters.Length; i++)
            {
                ParameterInfo parameterInfo = parametersInfo[i];
                if (parameterInfo.IsOut || parameterInfo.IsRetval)
                {
                    throw new InvalidOperationException(Strings.BaseServiceProvider_ParameterNotIn(method, parameterInfo));
                }

                ResourceType parameterType = PrimitiveResourceTypeMap.TypeMap.GetPrimitive(parameterInfo.ParameterType);
                if (parameterType == null)
                {
                    throw new InvalidOperationException(
                              Strings.BaseServiceProvider_ParameterTypeNotSupported(method, parameterInfo, parameterInfo.ParameterType));
                }

                string parameterName = parameterInfo.Name ?? "p" + i.ToString(CultureInfo.InvariantCulture);
                parameters[i] = new ServiceOperationParameter(parameterName, parameterType);
            }

            ResourceSet resourceSet = null;

            if (resourceType != null && resourceType.ResourceTypeKind == ResourceTypeKind.EntityType)
            {
                resourceSet = this.ResolveResourceSet(resourceType, method);

                if (resourceSet == null)
                {
                    throw new InvalidOperationException(
                              Strings.BaseServiceProvider_ServiceOperationMissingSingleEntitySet(method, resourceType.FullName));
                }
            }

            ServiceOperation operation = new ServiceOperation(method.Name, resultKind, resourceType, resourceSet, protocolMethod, parameters);

            operation.CustomState = method;

            MimeTypeAttribute attribute = BaseServiceProvider.GetMimeTypeAttribute(method);

            if (attribute != null)
            {
                operation.MimeType = attribute.MimeType;
            }

            return(operation);
        }