/// <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); }
/// <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); } }
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); }