/// <summary>
        /// Returns the resource type for the corresponding clr type.
        /// If the given clr type is a collection, then resource type describes the element type of the collection.
        /// </summary>
        /// <param name="type">clrType whose corresponding resource type needs to be returned</param>
        /// <returns>Returns the resource type</returns>
        private ResourceType GetNonPrimitiveType(Type type)
        {
            Debug.Assert(type != null, "type != null");

            // Check for the type directly first
            ResourceType resourceType = this.ResolveNonPrimitiveType(type);

            if (resourceType == null)
            {
                // check for ienumerable types
                Type elementType = BaseServiceProvider.GetIEnumerableElement(type);
                if (elementType != null)
                {
                    resourceType = ResourceType.GetPrimitiveResourceType(elementType);
                    if (resourceType == null)
                    {
                        resourceType = this.ResolveNonPrimitiveType(elementType);
                    }
                }
            }

            return(resourceType);
        }
Example #2
0
        /// <summary>
        /// Validate the parameters of the resource property constructor.
        /// </summary>
        /// <param name="kind">kind of the resource property.</param>
        /// <param name="propertyResourceType">resource type that this property refers to.</param>
        private static void ValidatePropertyParameters(ResourcePropertyKind kind, ResourceType propertyResourceType)
        {
            CheckResourcePropertyKind(kind, "kind");

            if (IsOfKind(kind, ResourcePropertyKind.ResourceReference) ||
                IsOfKind(kind, ResourcePropertyKind.ResourceSetReference))
            {
                if (propertyResourceType.ResourceTypeKind != ResourceTypeKind.EntityType)
                {
                    throw new ArgumentException(Strings.ResourceProperty_PropertyKindAndResourceTypeKindMismatch("kind",
                                                                                                                 "propertyResourceType"));
                }
            }

            if (IsOfKind(kind, ResourcePropertyKind.Primitive))
            {
                if (propertyResourceType.ResourceTypeKind != ResourceTypeKind.Primitive)
                {
                    throw new ArgumentException(Strings.ResourceProperty_PropertyKindAndResourceTypeKindMismatch("kind",
                                                                                                                 "propertyResourceType"));
                }
            }

            if (IsOfKind(kind, ResourcePropertyKind.ComplexType))
            {
                if (propertyResourceType.ResourceTypeKind != ResourceTypeKind.ComplexType)
                {
                    throw new ArgumentException(Strings.ResourceProperty_PropertyKindAndResourceTypeKindMismatch("kind",
                                                                                                                 "propertyResourceType"));
                }
            }

            if (IsOfKind(kind, ResourcePropertyKind.MultiValue))
            {
                if (propertyResourceType.ResourceTypeKind != ResourceTypeKind.MultiValue)
                {
                    throw new ArgumentException(Strings.ResourceProperty_PropertyKindAndResourceTypeKindMismatch("kind",
                                                                                                                 "propertyResourceType"));
                }
            }

            if (IsOfKind(kind, ResourcePropertyKind.Stream))
            {
                if (kind != ResourcePropertyKind.Stream)
                {
                    throw new ArgumentException(Strings.ResourceProperty_NamedStreamKindMustBeUsedAlone);
                }

                // Stream property should be declared on the Primitive Type Edm.Stream
                if (propertyResourceType != ResourceType.GetPrimitiveResourceType(typeof(System.IO.Stream)))
                {
                    throw new ArgumentException(Strings.ResourceProperty_PropertyKindAndResourceTypeKindMismatch("kind",
                                                                                                                 "propertyResourceType"));
                }
            }
            else if (propertyResourceType == ResourceType.GetPrimitiveResourceType(typeof(System.IO.Stream)))
            {
                // all other property kinds:
                throw new ArgumentException(Strings.ResourceProperty_PropertyKindAndResourceTypeKindMismatch("kind",
                                                                                                             "propertyResourceType"));
            }

            if (IsOfKind(kind, ResourcePropertyKind.Key) && Nullable.GetUnderlyingType(propertyResourceType.InstanceType) != null)
            {
                throw new ArgumentException(Strings.ResourceProperty_KeyPropertiesCannotBeNullable);
            }
        }
Example #3
0
 protected internal OperationParameter(string name, ResourceType parameterType)
 {
     WebUtil.CheckStringArgumentNullOrEmpty(name, "name");
     WebUtil.CheckArgumentNull <ResourceType>(parameterType, "parameterType");
     if ((parameterType.ResourceTypeKind == ResourceTypeKind.Primitive) && (parameterType == ResourceType.GetPrimitiveResourceType(typeof(Stream))))
     {
         throw new ArgumentException(Strings.ServiceOperationParameter_TypeNotSupported(name, parameterType.FullName), "parameterType");
     }
     this.name = name;
     this.type = parameterType;
 }
        /// <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);
        }