/// <summary>
        /// Infers resource sets and resource types corresponding to query operations in domain service.
        /// </summary>
        /// <param name="domainServiceDescription">Domain service description.</param>
        private void CollectResourceSets(DomainServiceDescription domainServiceDescription)
        {
            foreach (var operationEntry in domainServiceDescription.DomainOperationEntries)
            {
                // Only composable operations i.e. those that return IEnumerable<T> are expected to represent root resource sets.
                if (operationEntry.Operation == DomainOperation.Query && DomainDataServiceMetadata.IsRootQueryOperation(operationEntry))
                {
                    Type resourceInstanceType = operationEntry.AssociatedType;

                    // There will always be an entity type associated with query operation, we need to make sure that we have all
                    // the types in this type's hierarchy added to the provider types.
                    ResourceType resourceType = this.CreateResourceTypeHierarchy(domainServiceDescription, resourceInstanceType);

                    foreach (ResourceSet resourceSet in this.sets.Values)
                    {
                        Type resourceSetInstanceType = resourceSet.ResourceType.InstanceType;

                        if (resourceSetInstanceType.IsAssignableFrom(resourceInstanceType) ||
                            resourceInstanceType.IsAssignableFrom(resourceSetInstanceType))
                        {
                            throw new DomainDataServiceException((int)HttpStatusCode.InternalServerError, Resource.DomainDataService_MEST_NotAllowed);
                        }
                    }

                    ResourceSet rs = new ResourceSet(resourceInstanceType.Name + ServiceUtils.ResourceSetPostFix, resourceType);
                    this.sets.Add(operationEntry.Name, rs);
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Given an operation descriptions, detects if it corresponds to a root query operation.
        /// </summary>
        /// <param name="od">Given operation description.</param>
        /// <param name="metadata">Metadata for the domain data service.</param>
        /// <returns>null if operation does not correspond to root query operation, otherwise the name of the resource set.</returns>
        private static string GetRootQueryOperation(OperationDescription od, DomainDataServiceMetadata metadata)
        {
            ResourceSet resourceSet;

            if (metadata.Sets.TryGetValue(od.Name, out resourceSet))
            {
                Debug.Assert(resourceSet != null, "resourceSet != null");
                return(resourceSet.Name);
            }

            return(null);
        }
        /// <summary>
        /// Infers service operations from domain service description.
        /// </summary>
        /// <param name="domainServiceDescription">Domain service description.</param>
        private void CollectServiceOperations(DomainServiceDescription domainServiceDescription)
        {
            foreach (var operationEntry in domainServiceDescription.DomainOperationEntries)
            {
                DomainDataServiceOperation op = null;

                if ((operationEntry.Operation == DomainOperation.Query && !DomainDataServiceMetadata.IsRootQueryOperation(operationEntry)) ||
                    operationEntry.Operation == DomainOperation.Invoke)
                {
                    op = this.CreateServiceOperation(operationEntry);
                }

                if (op != null)
                {
                    this.serviceOperations.Add(op.Name, op);
                }
            }
        }
Пример #4
0
        /// <summary>Constructs the operation selector for runtime.</summary>
        /// <param name="endpoint">End point.</param>
        /// <param name="metadata">Domain data service metadata.</param>
        public DomainDataServiceOperationSelector(
            ServiceEndpoint endpoint,
            DomainDataServiceMetadata metadata)
            : base(DomainDataServiceOperationSelector.ExtractNonRootQueryServiceOperations(endpoint, metadata))
        {
            this.baseUri = endpoint.ListenUri;
            this.serviceRootQueryOperations = new Dictionary <string, string>();

            // Collect all the query operations, since they are to be handled by selector in this class.
            foreach (var od in endpoint.Contract.Operations)
            {
                string resourceSetName = DomainDataServiceOperationSelector.GetRootQueryOperation(od, metadata);
                if (!String.IsNullOrEmpty(resourceSetName))
                {
                    Debug.Assert(!this.serviceRootQueryOperations.ContainsKey(resourceSetName), "There should only be 1 default query operation per set.");

                    // Note the fact that requests on resourceSet correspond to the given operation.
                    this.serviceRootQueryOperations.Add(resourceSetName, od.Name);
                }
            }
        }
Пример #5
0
 /// <summary>Constructs the data service provider object.</summary>
 /// <param name="domainServiceDataServiceMetadata">Metadata information for the current instance.</param>
 /// <param name="result">Root queryable for current request.</param>
 internal DomainDataServiceProvider(DomainDataServiceMetadata domainServiceDataServiceMetadata, object result)
 {
     this.metadata          = domainServiceDataServiceMetadata;
     this.CurrentDataSource = new object();
     this.Result            = result;
 }
 /// <summary>
 /// Creates a new domain data service instance.
 /// </summary>
 /// <param name="domainServiceDataServiceMetadata">Metadata for the domain data service.</param>
 /// <param name="result">Result of current request operation invocation.</param>
 internal DomainDataService(DomainDataServiceMetadata domainServiceDataServiceMetadata, object result)
 {
     this.provider = new DomainDataServiceProvider(domainServiceDataServiceMetadata, result);
 }
Пример #7
0
        /// <summary>
        /// Obtains the service operations available on the model and hands over all those
        /// operations to the base class for processing. The root query operations are
        /// handled by this class itself.
        /// </summary>
        /// <param name="endpoint">Endpoint on which operations are defined.</param>
        /// <param name="metadata">Metadata of the domain service.</param>
        /// <returns>Endpoint that contains all the operations that base class needs to process.</returns>
        private static ServiceEndpoint ExtractNonRootQueryServiceOperations(ServiceEndpoint endpoint, DomainDataServiceMetadata metadata)
        {
            ContractDescription cd = new ContractDescription(endpoint.Contract.Name);

            // Provide all the non-root query operations to the base class, only provide those operations that
            // have some representation on the domain data service.
            foreach (OperationDescription od in endpoint.Contract.Operations)
            {
                if (metadata.ServiceOperations.Keys.Contains(od.Name))
                {
                    Debug.Assert(
                        String.IsNullOrEmpty(DomainDataServiceOperationSelector.GetRootQueryOperation(od, metadata)),
                        "Service operation must not be a root query operation.");
                    cd.Operations.Add(od);
                }
            }

            return(new ServiceEndpoint(cd, endpoint.Binding, endpoint.Address)
            {
                ListenUri = endpoint.ListenUri
            });
        }
Пример #8
0
 /// <summary>Constructs factory for creating data services using the given domain service description.</summary>
 /// <param name="metadata">Data Service metadata object corresponding to domain service description.</param>
 internal DomainDataServiceFactory(DomainDataServiceMetadata metadata)
 {
     this.domainDataServiceMetadata = metadata;
 }
        /// <summary>
        /// Loads properties for all the resource types.
        /// </summary>
        private void LoadResourceTypeProperties()
        {
#if DEBUG
            // Remember the types we've visited.
            HashSet <ResourceType> visitedType = new HashSet <ResourceType>(EqualityComparer <ResourceType> .Default);
#endif
            foreach (var resourceType in this.types.Values)
            {
                Type         type = resourceType.InstanceType;
                ResourceType parentResourceType = resourceType.BaseType;
#if DEBUG
                Debug.Assert(parentResourceType == null || visitedType.Contains(parentResourceType), "We must always visit the ancestors of a type before visiting that type.");
                visitedType.Add(resourceType);
#endif
                foreach (PropertyDescriptor pi in TypeDescriptor.GetProperties(type))
                {
                    if (!TypeUtils.IsSerializableDataMember(pi))
                    {
                        continue;
                    }

                    // Only primitive properties are currently supported.
                    ResourceType propertyType = ResourceType.GetPrimitiveResourceType(pi.PropertyType);

                    if (null != propertyType)
                    {
                        ResourceProperty rp = parentResourceType == null ?
                                              null :
                                              this.GetResourceProperty(parentResourceType, DomainDataServiceMetadata.GetNameFromPropertyDescriptor(pi));

                        if (rp == null)
                        {
                            ResourcePropertyKind kind = ResourcePropertyKind.Primitive;
                            if (TypeUtils.IsKeyProperty(pi))
                            {
                                kind |= ResourcePropertyKind.Key;
                            }

                            rp = new ResourceProperty(
                                DomainDataServiceMetadata.GetNameFromPropertyDescriptor(pi),
                                kind,
                                propertyType)
                            {
                                CanReflectOnInstanceTypeProperty = false
                            };

                            // We only need to add rp to the resourceType if rp is not defined on an ancestor type.
                            resourceType.AddProperty(rp);
                        }

                        // We always add rp to this.resourceProperties map even if the property is defined on an ancestor type.
                        this.AddResourcePropertyDescriptor(resourceType, rp, pi);
                    }
                }
            }

#if DEBUG
            foreach (var entry in this.resourceProperties)
            {
                Debug.Assert(entry.Value.Count > 0, "A ResourceType cannot have 0 properties, it should have at least its key property.");
            }
#endif
        }