public DataServiceQueryProvider(DataServiceMetadataProvider metadata)
 {
     _metadata = metadata;
 }
 private DataServiceQueryProvider <T> GetQueryProvider(DataServiceMetadataProvider metadata)
 {
     return(new DataServiceQueryProvider <T>(_metadata));
 }
        private static DataServiceMetadataProvider GetMetadataProvider(Type dataSourceType)
        {
            if (_mdprovider != null)
            {
                return(_mdprovider);
            }

            var exposedTypes    = GetExposedTypes(dataSourceType);
            var collectionNames = GetCollectionNames(dataSourceType);
            var mdprovider      = new DataServiceMetadataProvider(collectionNames);
            var resourceTypes   = new Dictionary <string, ResourceType>();

            foreach (var exposedType in exposedTypes)
            {
                // create type
                var odataType = new ResourceType(exposedType, ResourceTypeKind.EntityType, null, "BrightstarEntities",
                                                 NormaliseName(exposedType.Name), false);
                resourceTypes.Add(NormaliseName(exposedType.Name), odataType);

                // create primitive properties
                foreach (var propertyInfo in exposedType.GetProperties())
                {
                    var name = propertyInfo.Name;
                    if (!propertyInfo.PropertyType.IsGenericType && IsLiteral(propertyInfo))
                    {
                        if (propertyInfo.Name.ToLower().Equals("id"))
                        {
                            var idProperty = new ResourceProperty(
                                propertyInfo.Name,
                                ResourcePropertyKind.Key |
                                ResourcePropertyKind.Primitive,
                                ResourceType.GetPrimitiveResourceType(typeof(string))
                                );
                            odataType.AddProperty(idProperty);
                        }
                        else
                        {
                            var valueProperty = new ResourceProperty(
                                propertyInfo.Name,
                                ResourcePropertyKind.Primitive,
                                ResourceType.GetPrimitiveResourceType(propertyInfo.PropertyType)
                                );
                            odataType.AddProperty(valueProperty);
                        }
                    }
                    else
                    {
                        if (IsNullableLiteral(propertyInfo))
                        {
                            var valueProperty = new ResourceProperty(
                                propertyInfo.Name,
                                ResourcePropertyKind.Primitive,
                                ResourceType.GetPrimitiveResourceType(propertyInfo.PropertyType)
                                );
                            odataType.AddProperty(valueProperty);
                        }
                    }
                }
            }

            // make resource sets
            var resourceSets = new Dictionary <string, ResourceSet>();

            foreach (var resourceType in resourceTypes.Values)
            {
                resourceSets.Add(resourceType.Name, new ResourceSet(resourceType.Name, resourceType));
            }

            var associationSets = new Dictionary <string, ResourceAssociationSet>();

            foreach (var exposedType in exposedTypes)
            {
                foreach (var propertyInfo in exposedType.GetProperties())
                {
                    // ignore inverse properties as they get sorted out later.
                    if (IsInverseProperty(propertyInfo))
                    {
                        continue;
                    }

                    if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.Name.StartsWith("ICollection"))
                    {
                        var referencedType = propertyInfo.PropertyType.GetGenericArguments()[0];

                        var referencedTypeName = NormaliseName(referencedType.Name);
                        // skip non entity collections
                        if (!resourceTypes.ContainsKey(referencedTypeName))
                        {
                            continue;
                        }

                        // add reference set relationship
                        var referenceSetProperty = new ResourceProperty(
                            propertyInfo.Name,
                            ResourcePropertyKind.ResourceSetReference,
                            resourceTypes[NormaliseName(referencedType.Name)]);

                        resourceTypes[NormaliseName(exposedType.Name)].AddProperty(referenceSetProperty);

                        var inversePropertyInfo = FindInversePropertyFor(propertyInfo);
                        if (inversePropertyInfo == null)
                        {
                            var assocSet = new ResourceAssociationSet(propertyInfo.Name,
                                                                      new ResourceAssociationSetEnd(
                                                                          resourceSets[NormaliseName(exposedType.Name)],
                                                                          resourceTypes[NormaliseName(exposedType.Name)],
                                                                          referenceSetProperty),
                                                                      new ResourceAssociationSetEnd(
                                                                          resourceSets[NormaliseName(referencedType.Name)],
                                                                          resourceTypes[NormaliseName(referencedType.Name)],
                                                                          null));
                            referenceSetProperty.CustomState = assocSet;
                        }
                        else
                        {
                            // create the inverse resource property
                            ResourceProperty inverseReferenceProperty = null;
                            if (inversePropertyInfo.PropertyType.IsGenericType)
                            {
                                inverseReferenceProperty = new ResourceProperty(
                                    inversePropertyInfo.Name,
                                    ResourcePropertyKind.ResourceSetReference,
                                    resourceTypes[NormaliseName(inversePropertyInfo.PropertyType.GetGenericArguments()[0].Name)]);
                            }
                            else
                            {
                                inverseReferenceProperty = new ResourceProperty(
                                    inversePropertyInfo.Name,
                                    ResourcePropertyKind.ResourceReference,
                                    resourceTypes[NormaliseName(inversePropertyInfo.PropertyType.Name)]);
                            }

                            resourceTypes[NormaliseName(inversePropertyInfo.ReflectedType.Name)].AddProperty(inverseReferenceProperty);

                            // we need to create the other property as well as the association
                            var assocSet = new ResourceAssociationSet(referenceSetProperty.Name + "_" + inverseReferenceProperty.Name,
                                                                      new ResourceAssociationSetEnd(
                                                                          resourceSets[NormaliseName(exposedType.Name)],
                                                                          resourceTypes[NormaliseName(exposedType.Name)],
                                                                          referenceSetProperty),
                                                                      new ResourceAssociationSetEnd(
                                                                          resourceSets[NormaliseName(referencedType.Name)],
                                                                          resourceTypes[NormaliseName(referencedType.Name)],
                                                                          inverseReferenceProperty));
                            referenceSetProperty.CustomState     = assocSet;
                            inverseReferenceProperty.CustomState = assocSet;
                        }
                    }
                    else if (resourceTypes.Keys.Contains(NormaliseName(propertyInfo.PropertyType.Name)))
                    {
                        var referenceProperty = new ResourceProperty(
                            propertyInfo.Name,
                            ResourcePropertyKind.ResourceReference,
                            resourceTypes[NormaliseName(propertyInfo.PropertyType.Name)]);
                        resourceTypes[NormaliseName(exposedType.Name)].AddProperty(referenceProperty);
                        var inversePropertyInfo = FindInversePropertyFor(propertyInfo);
                        if (inversePropertyInfo == null)
                        {
                            var assocSet = new ResourceAssociationSet(referenceProperty.Name,
                                                                      new ResourceAssociationSetEnd(
                                                                          resourceSets[NormaliseName(exposedType.Name)],
                                                                          resourceTypes[NormaliseName(exposedType.Name)],
                                                                          referenceProperty),
                                                                      new ResourceAssociationSetEnd(
                                                                          resourceSets[NormaliseName(propertyInfo.PropertyType.Name)],
                                                                          resourceTypes[NormaliseName(propertyInfo.PropertyType.Name)],
                                                                          null));
                            referenceProperty.CustomState = assocSet;
                        }
                        else
                        {
                            // create the inverse resource property
                            ResourceProperty inverseReferenceProperty = null;

                            if (inversePropertyInfo.PropertyType.IsGenericType)
                            {
                                inverseReferenceProperty = new ResourceProperty(
                                    inversePropertyInfo.Name,
                                    ResourcePropertyKind.ResourceSetReference,
                                    resourceTypes[NormaliseName(inversePropertyInfo.PropertyType.GetGenericArguments()[0].Name)]);
                            }
                            else
                            {
                                inverseReferenceProperty = new ResourceProperty(
                                    inversePropertyInfo.Name,
                                    ResourcePropertyKind.ResourceReference,
                                    resourceTypes[NormaliseName(inversePropertyInfo.PropertyType.Name)]);
                            }

                            resourceTypes[NormaliseName(inversePropertyInfo.ReflectedType.Name)].AddProperty(inverseReferenceProperty);

                            // we need to create the other property as well as the association
                            var assocSet = new ResourceAssociationSet(referenceProperty.Name + "_" + inverseReferenceProperty.Name,
                                                                      new ResourceAssociationSetEnd(
                                                                          resourceSets[NormaliseName(exposedType.Name)],
                                                                          resourceTypes[NormaliseName(exposedType.Name)],
                                                                          referenceProperty),
                                                                      new ResourceAssociationSetEnd(
                                                                          resourceSets[NormaliseName(propertyInfo.PropertyType.Name)],
                                                                          resourceTypes[NormaliseName(propertyInfo.PropertyType.Name)],
                                                                          inverseReferenceProperty));
                            referenceProperty.CustomState        = assocSet;
                            inverseReferenceProperty.CustomState = assocSet;
                        }
                    }
                }
            }


            foreach (var resourceAssociationSet in associationSets.Values)
            {
                mdprovider.AddAssociationSet(resourceAssociationSet);
            }

            foreach (var resourceType in resourceTypes.Values)
            {
                mdprovider.AddResourceType(resourceType);
                mdprovider.AddResourceSet(resourceSets[resourceType.Name]);
            }

            _mdprovider = mdprovider;
            return(_mdprovider);
        }
 /// <summary>
 /// Creates a new entity data service. This is the default constructor called by the ServiceHost.
 /// </summary>
 protected EntityDataService()
 {
     _metadata = GetMetadataProvider(typeof(T));
     _query    = GetQueryProvider(_metadata);
 }