Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Server / System / Data / Services / Providers / BaseServiceProvider.cs / 1305376 / BaseServiceProvider.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // //// Abstract Class which contains the common code for ObjectContextServiceProvider // and ReflectionServiceProvider // // // @owner [....] //--------------------------------------------------------------------- namespace System.Data.Services.Providers { #region Namespaces. using System; using System.Collections; using System.Collections.Generic; using System.Data.Services.Caching; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.ServiceModel.Web; #endregion Namespaces. ///Provides a reflection-based provider implementation. internal abstract class BaseServiceProvider : IDataServiceMetadataProvider, IDataServiceQueryProvider, IDisposable, IProjectionProvider, IServiceProvider { ///Bindings Flags to be used for reflection. protected const BindingFlags ResourceContainerBindingFlags = WebUtil.PublicInstanceBindingFlags; ///Instance from which data is provided. private object instance; ///Metadata to be used by the service provider. private MetadataCacheItem metadata; ///instance of the service to invoke service operations. private object dataServiceInstance; ////// Reference back to the provider wrapper. /// private DataServiceProviderWrapper providerWrapper; ////// Initializes a new System.Data.Services.BaseServiceProvider instance. /// /// Metadata for this provider. /// data service instance. protected BaseServiceProvider(MetadataCacheItem metadata, object dataServiceInstance) { WebUtil.CheckArgumentNull(metadata, "metadata"); WebUtil.CheckArgumentNull(dataServiceInstance, "dataServiceInstance"); this.metadata = metadata; this.dataServiceInstance = dataServiceInstance; } #region IDataServiceQueryProvider Properties ///Returns the instance from which data is provided. public object CurrentDataSource { [DebuggerStepThrough] get { // Many debuggers will try to display this property, and we don't want to trigger an assertion. Debug.Assert( System.Diagnostics.Debugger.IsAttached || this.instance != null, "this.instance != null -- otherwise CurrentDataSource is accessed before initialization or after disposal."); return this.instance; } set { WebUtil.CheckArgumentNull(value, "value"); this.instance = value; } } ///Gets a value indicating whether null propagation is required in expression trees. public abstract bool IsNullPropagationRequired { get; } #endregion IDataServiceQueryProvider Properties #region IDataServiceMetadataProvider Properties ///Namespace name for the EDM container. public abstract string ContainerNamespace { get; } ///Name of the EDM container public abstract string ContainerName { get; } ///Gets all available containers. ///An enumerable object with all available containers. public IEnumerableResourceSets { get { return this.EntitySets.Values; } } /// Returns all the types in this data source public IEnumerableTypes { get { return this.metadata.TypeCache.Values; } } /// Returns all known service operations. public IEnumerableServiceOperations { get { foreach (ServiceOperation serviceOperation in this.metadata.ServiceOperations.Values) { yield return serviceOperation; } } } #endregion IDataServiceMetadataProvider Properties /// EDM version to which metadata is compatible. ////// For example, a service operation of type Void is not acceptable 1.0 CSDL, /// so it should use 1.1 CSDL instead. Similarly, OpenTypes are supported /// in 1.2 and not before. /// internal MetadataEdmSchemaVersion EdmSchemaVersion { get { return this.metadata.EdmSchemaVersion; } } ///Whether all EPM properties serialize in an Astoria V1-compatible way. ////// This property is false if any property has KeepInContent set to false. /// internal bool EpmIsV1Compatible { [DebuggerStepThrough] get { return this.metadata.EpmIsV1Compatible; } } ////// Reference back to the provider wrapper. /// internal DataServiceProviderWrapper ProviderWrapper { set { this.providerWrapper = value; } get { Debug.Assert(this.providerWrapper != null, "this.providerWrapper != null"); return this.providerWrapper; } } ///Returns the list of entity sets. protected IDictionaryEntitySets { [DebuggerStepThrough] get { return this.metadata.EntitySets; } } /// Target type for the data provider protected Type Type { [DebuggerStepThrough] get { return this.metadata.Type; } } ///Cache of resource properties per type. private DictionaryTypeCache { [DebuggerStepThrough] get { return this.metadata.TypeCache; } } /// Cache of immediate derived types per type. private Dictionary> ChildTypesCache { [DebuggerStepThrough] get { return this.metadata.ChildTypesCache; } } #region Public Methods /// Applies expansions and projections to the specified ///. object to expand and apply projections to. /// The root node of the tree which describes /// the projections and expansions to be applied to the . /// /// An ///object, with the results including /// the expansions and projections specified in . /// /// The returned public abstract IQueryable ApplyProjections( IQueryable source, ProjectionNode projection); ///may implement the interface /// to provide enumerable objects for the expansions; otherwise, the expanded /// information is expected to be found directly in the enumerated objects. If paging is /// requested by providing a non-empty list in .OrderingInfo then /// it is expected that the topmost would have a $skiptoken property /// which will be an in itself and each of it's sub-properties will /// be named SkipTokenPropertyXX where XX represents numbers in increasing order starting from 0. Each of /// SkipTokenPropertyXX properties will be used to generated the $skiptoken to support paging. /// If projections are required, the provider may choose to return /// which returns instances of . In that case property values are determined /// by calling the method instead of /// accessing properties of the returned object directly. /// If both expansion and projections are required, the provider may choose to return /// of which in turn returns from its /// property. /// /// Gets the ResourceAssociationSet instance when given the source association end. /// /// Resource set of the source association end. /// Resource type of the source association end. /// Resource property of the source association end. ///ResourceAssociationSet instance. public abstract ResourceAssociationSet GetResourceAssociationSet(ResourceSet resourceSet, ResourceType resourceType, ResourceProperty resourceProperty); ////// Checks whether the specified /// Type to check. ///is ordered. /// true if the type may be ordered; false otherwise. ////// The ordering may still fail at runtime; this method is currently /// used for cleaner error messages only. /// public virtual bool GetTypeIsOrdered(Type type) { Debug.Assert(type != null, "type != null"); return type == typeof(object) || WebUtil.IsPrimitiveType(type); } ////// Returns the requested service /// /// type of service you are requesting for. ///returns the instance of the requested service. public virtual object GetService(Type serviceType) { if (typeof(IDataServiceMetadataProvider) == serviceType || typeof(IDataServiceQueryProvider) == serviceType || typeof(IProjectionProvider) == serviceType) { return this; } return null; } ///Releases the current data source object as necessary. void IDisposable.Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } #endregion Public Methods #region IDataServiceQueryProvider Methods ////// Returns the IQueryable that represents the container. /// /// resource set representing the entity set. ////// An IQueryable that represents the container; null if there is /// no container for the specified name. /// public IQueryable GetQueryRootForResourceSet(ResourceSet container) { Debug.Assert(container != null, "resourceContainer != null"); return this.GetResourceContainerInstance(container); } ///Gets the /// Instance to extract afor the specified . from. /// The public ResourceType GetResourceType(object resource) { Debug.Assert(resource != null, "instance != null"); return this.GetNonPrimitiveType(resource.GetType()); } ///that describes this in this provider. /// Get the value of the strongly typed property. /// /// instance of the type declaring the property. /// resource property describing the property. ///value for the property. public object GetPropertyValue(object target, ResourceProperty resourceProperty) { Debug.Assert(target != null, "target != null"); Debug.Assert(resourceProperty != null, "resourceProperty != null"); try { PropertyInfo propertyInfo = this.GetResourceType(target).GetPropertyInfo(resourceProperty); Debug.Assert(propertyInfo != null, "propertyInfo != null"); return propertyInfo.GetGetMethod().Invoke(target, null); } catch (TargetInvocationException exception) { ErrorHandler.HandleTargetInvocationException(exception); throw; } } ////// Gets the value of the open property. /// /// instance of the resource type. /// name of the property. ///the value of the open property. If the property is not present, return null. public abstract object GetOpenPropertyValue(object target, string propertyName); ////// Get the name and values of all the properties defined in the given instance of an open type. /// /// instance of a open type. ///collection of name and values of all the open properties. public abstract IEnumerable> GetOpenPropertyValues(object target); /// /// Invoke the given service operation instance. /// /// metadata for the service operation to invoke. /// list of parameters to pass to the service operation. ///returns the result by the service operation instance. public object InvokeServiceOperation(ServiceOperation serviceOperation, object[] parameters) { return ((MethodInfo)serviceOperation.CustomState).Invoke( this.dataServiceInstance, BindingFlags.Instance | BindingFlags.Instance | BindingFlags.FlattenHierarchy, null, parameters, Globalization.CultureInfo.InvariantCulture); } #endregion IDataServiceQueryProvider Methods #region IDataServiceMetadataProvider Methods ////// The method must return a collection of all the types derived from /// Resource to get derived resource types from. ///. /// The collection returned should NOT include the type passed in as a parameter. /// An implementer of the interface should return null if the type does not have any derived types (ie. null == no derived types). /// /// A collection of resource types ( public IEnumerable) derived from the specified /// or null if there no types derived from the specified exist. /// GetDerivedTypes(ResourceType resourceType) { Debug.Assert(resourceType != null, "resourceType != null"); Debug.Assert(this.ChildTypesCache.ContainsKey(resourceType), "this.ChildTypesCache.ContainsKey(resourceType)"); List childTypes = this.ChildTypesCache[resourceType]; if (childTypes != null) { foreach (ResourceType childType in childTypes) { yield return childType; foreach (ResourceType descendantType in this.GetDerivedTypes(childType)) { yield return descendantType; } } } } /// /// Returns true if /// instance of the resource type in question. ///represents an Entity Type which has derived Entity Types, else false. /// True if public bool HasDerivedTypes(ResourceType resourceType) { Debug.Assert(resourceType != null, "resourceType != null"); Debug.Assert(this.ChildTypesCache.ContainsKey(resourceType), "this.ChildTypesCache.ContainsKey(resourceType)"); Debug.Assert(this.ChildTypesCache[resourceType] == null || this.ChildTypesCache[resourceType].Count > 0, "this.ChildTypesCache[resourceType] == null || this.ChildTypesCache[resourceType].Count > 0"); return this.ChildTypesCache[resourceType] != null; } ///represents an Entity Type which has derived Entity Types, else false. Given the specified name, tries to find a resource set. /// Name of the resource set to resolve. /// Returns the resolved resource set, null if no resource set for the given name was found. ///True if resource set with the given name was found, false otherwise. public bool TryResolveResourceSet(string name, out ResourceSet resourceSet) { Debug.Assert(!string.IsNullOrEmpty(name), "!string.IsNullOrEmpty(name)"); return this.EntitySets.TryGetValue(name, out resourceSet); } ///Given the specified name, tries to find a service operation. /// Name of the service operation to resolve. /// Returns the resolved service operation, null if no service operation was found for the given name. ///True if we found the service operation for the given name, false otherwise. public bool TryResolveServiceOperation(string name, out ServiceOperation serviceOperation) { Debug.Assert(!string.IsNullOrEmpty(name), "!string.IsNullOrEmpty(name)"); return this.metadata.ServiceOperations.TryGetValue(name, out serviceOperation); } ///Given the specified name, tries to find a type. /// Name of the type to resolve. /// Returns the resolved resource type, null if no resource type for the given name was found. ///True if we found the resource type for the given name, false otherwise. public bool TryResolveResourceType(string name, out ResourceType resourceType) { Debug.Assert(!string.IsNullOrEmpty(name), "!string.IsNullOrEmpty(name)"); Debug.Assert(this.metadata != null, "this.metadata != null"); Debug.Assert(this.TypeCache != null, "this.TypeCache != null"); foreach (ResourceType t in this.TypeCache.Values) { if (t.FullName == name) { resourceType = t; return true; } } resourceType = null; return false; } #endregion IDataServiceMetadataProvider Methods #region Internal Methods ////// Returns the type of the IEnumerable if the type implements IEnumerable interface; null otherwise. /// /// type that needs to be checked ///Element type if the type implements IEnumerable, else returns null internal static Type GetIEnumerableElement(Type type) { return GetGenericInterfaceElementType(type, IEnumerableTypeFilter); } ////// Returns the "T" in the IQueryable of T implementation of type. /// /// Type to check. /// filter against which the type is checked ////// The element type for the generic IQueryable interface of the type, /// or null if it has none or if it's ambiguous. /// internal static Type GetGenericInterfaceElementType(Type type, TypeFilter typeFilter) { Debug.Assert(type != null, "type != null"); Debug.Assert(!type.IsGenericTypeDefinition, "!type.IsGenericTypeDefinition"); if (typeFilter(type, null)) { return type.GetGenericArguments()[0]; } Type[] queriables = type.FindInterfaces(typeFilter, null); if (queriables != null && queriables.Length == 1) { return queriables[0].GetGenericArguments()[0]; } else { return null; } } ////// Checks whether the provider implements IUpdatable. /// ///returns true if the provider implements IUpdatable. otherwise returns false. internal abstract bool ImplementsIUpdatable(); ///Adds service operations based on methods of the specified type. /// Type with methods to add. internal void AddOperationsFromType(Type type) { Debug.Assert(type != null, "type != null"); foreach (MethodInfo methodInfo in type.GetMethods(WebUtil.PublicInstanceBindingFlags | BindingFlags.FlattenHierarchy)) { if (methodInfo.GetCustomAttributes(typeof(WebGetAttribute), true).Length != 0) { this.AddServiceOperation(methodInfo, XmlConstants.HttpMethodGet); } else if (methodInfo.GetCustomAttributes(typeof(WebInvokeAttribute), true).Length != 0) { this.AddServiceOperation(methodInfo, XmlConstants.HttpMethodPost); } } } ///Populates the metadata for the given provider. internal void PopulateMetadata() { Debug.Assert(this.metadata != null, "this.metadata != null -- otherwise we don't have an item to populate"); this.PopulateMetadata(this.TypeCache, this.ChildTypesCache, this.EntitySets); } ////// Applies access rights to entity sets /// /// Data service configuration instance with access right info. internal void ApplyConfiguration(DataServiceConfiguration configuration) { Debug.Assert(configuration != null, "configuration != null"); this.PopulateMetadataForUserSpecifiedTypes(configuration.GetKnownTypes(), this.TypeCache, this.ChildTypesCache, this.EntitySets.Values); this.CheckConfigurationConsistency(this.instance, configuration); } ///Make all the metadata readonly internal void MakeMetadataReadonly() { foreach (ResourceSet container in this.ResourceSets) { container.SetReadOnly(); } foreach (ResourceType resourceType in this.Types) { resourceType.SetReadOnly(); if (!resourceType.EpmIsV1Compatible) { this.metadata.EpmIsV1Compatible = false; } } foreach (ServiceOperation operation in this.ServiceOperations) { operation.SetReadOnly(); } } #endregion Internal Methods #region Protected methods. ////// Returns the type of the IQueryable if the type implements IQueryable interface /// /// clr type on which IQueryable check needs to be performed. ///Element type if the property type implements IQueryable, else returns null protected static Type GetIQueryableElement(Type type) { return GetGenericInterfaceElementType(type, IQueryableTypeFilter); } ////// Find the corresponding ResourceType for a given Type, primitive or not /// /// Non-primitive types to search /// Type to look for /// Corresponding ResourceType, if found ///True if type found, false otherwise protected static bool TryGetType(IDictionaryknownTypes, Type type, out ResourceType resourceType) { Debug.Assert(knownTypes != null, "knownTypes != null"); Debug.Assert(type != null, "type != null"); resourceType = ResourceType.GetPrimitiveResourceType(type); if (resourceType == null) { knownTypes.TryGetValue(type, out resourceType); } return resourceType != null; } /// Checks that the applied configuration is consistent. /// Instance of the data source for the provider. /// Data service configuration instance with access right info. ///At this point in initialization, metadata trimming hasn't taken place. protected virtual void CheckConfigurationConsistency(object dataSourceInstance, DataServiceConfiguration configuration) { } ///Releases the current data source object as necessary. /// /// Whether this method is called from an explicit call to Dispose by /// the consumer, rather than during finalization. /// protected virtual void Dispose(bool disposing) { WebUtil.Dispose(this.instance); this.instance = null; } ////// Returns the resource type of the given instance and validates that the instance returns a single resource. /// /// clr instance of a resource. ///resource type of the given instance. protected ResourceType GetSingleResource(object resource) { ResourceType resourceType = this.ProviderWrapper.GetResourceType(resource); return resourceType; } ////// Creates the object query for the given resource set and returns it /// /// resource set for which IQueryable instance needs to be created ///returns the IQueryable instance for the given resource set protected abstract IQueryable GetResourceContainerInstance(ResourceSet resourceContainer); ////// Populates the metadata for the given provider /// /// list of known types /// list of known types and their immediate children /// list of entity sets protected abstract void PopulateMetadata( IDictionaryknownTypes, IDictionary > childTypes, IDictionary entitySets); /// /// Populate types for metadata specified by the provider /// /// list of types specified by the provider /// list of already known types /// list of already known types and their immediate children /// list of entity sets as specified in the data source type protected abstract void PopulateMetadataForUserSpecifiedTypes(IEnumerableuserSpecifiedTypes, IDictionary knownTypes, IDictionary > childTypes, IEnumerable entitySets); /// /// Populate metadata for the given clr type. /// /// type whose metadata needs to be loaded. /// list of already known resource types. /// list of already known types and their immediate children /// list of entity sets as specified in the data source. ///resource type containing metadata for the given clr type. protected abstract ResourceType PopulateMetadataForType(Type type, IDictionaryknownTypes, IDictionary > childTypes, IEnumerable entitySets); #endregion Protected methods. #region Private Methods /// Filter callback for finding IQueryable implementations. /// Type to inspect. /// Filter criteria. ///true if the specified type is an IQueryable of T; false otherwise. private static bool IQueryableTypeFilter(Type m, object filterCriteria) { Debug.Assert(m != null, "m != null"); return m.IsGenericType && m.GetGenericTypeDefinition() == typeof(IQueryable<>); } ///Filter callback for finding IEnumerable implementations. /// Type to inspect. /// Filter criteria. ///true if the specified type is an IEnumerable of T; false otherwise. private static bool IEnumerableTypeFilter(Type m, object filterCriteria) { Debug.Assert(m != null, "m != null"); return m.IsGenericType && m.GetGenericTypeDefinition() == typeof(IEnumerable<>); } ///Updates the EDM schema version if it is currently lower than /// New version for EDM schema. private void UpdateEdmSchemaVersion(MetadataEdmSchemaVersion newVersion) { if (this.metadata.EdmSchemaVersion < newVersion) { this.metadata.EdmSchemaVersion = newVersion; } } ///. /// Adds a new /// Method to expose as a service operation. /// Protocol (for example HTTP) method the service operation responds to. 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); } ///based on the specified /// instance. /// /// 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. /// /// clrType whose corresponding resource type needs to be returned ///Returns the resource type private ResourceType GetNonPrimitiveType(Type type) { Debug.Assert(type != null, "type != null"); // Check for the type directly first ResourceType resourceType; if (this.TypeCache.TryGetValue(type, out resourceType)) { return resourceType; } // check for ienumerable types Type elementType = BaseServiceProvider.GetIEnumerableElement(type); if (elementType != null) { resourceType = ResourceType.GetPrimitiveResourceType(elementType); if (resourceType == null) { this.TypeCache.TryGetValue(elementType, out resourceType); } } return resourceType; } ////// Looks for the first resource set that the specified /// Type to look for. /// After the method returns, the container to which the type could belong. ////// could belong to. /// true if a container was found; false otherwise. private bool TryFindAnyContainerForType(ResourceType type, out ResourceSet container) { Debug.Assert(type != null, "type != null"); foreach (ResourceSet c in this.EntitySets.Values) { if (c.ResourceType.IsAssignableFrom(type)) { container = c; return true; } } container = default(ResourceSet); return false; } #endregion Private Methods #region QueryableOverEnumerable #if DEBUG ///Implementation of the ///interface which only support /// the enumerable portion of the interface. Used for the old internal class QueryableOverEnumerable : IQueryable { ///which returns /// but we require instead. The private readonly IEnumerable enumerable; ///this object wraps. Constructor - creates new instance. /// Theto wrap with . internal QueryableOverEnumerable(IEnumerable enumerable) { this.enumerable = enumerable; } /// The type of the element - not implemented as nothing should call this. public Type ElementType { get { throw new NotImplementedException(); } } ///The expression for the query - not implemented as nothing should call this. public System.Linq.Expressions.Expression Expression { get { throw new NotImplementedException(); } } ///The query provider for this query - not implemented as nothing should call this. public IQueryProvider Provider { get { throw new NotImplementedException(); } } ///Creates new enumerator of the results of this query. ///New public IEnumerator GetEnumerator() { return this.enumerable.GetEnumerator(); } } #endif #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- //to enumerate results of this query. // Copyright (c) Microsoft Corporation. All rights reserved. // //// Abstract Class which contains the common code for ObjectContextServiceProvider // and ReflectionServiceProvider // // // @owner [....] //--------------------------------------------------------------------- namespace System.Data.Services.Providers { #region Namespaces. using System; using System.Collections; using System.Collections.Generic; using System.Data.Services.Caching; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.ServiceModel.Web; #endregion Namespaces. ///Provides a reflection-based provider implementation. internal abstract class BaseServiceProvider : IDataServiceMetadataProvider, IDataServiceQueryProvider, IDisposable, IProjectionProvider, IServiceProvider { ///Bindings Flags to be used for reflection. protected const BindingFlags ResourceContainerBindingFlags = WebUtil.PublicInstanceBindingFlags; ///Instance from which data is provided. private object instance; ///Metadata to be used by the service provider. private MetadataCacheItem metadata; ///instance of the service to invoke service operations. private object dataServiceInstance; ////// Reference back to the provider wrapper. /// private DataServiceProviderWrapper providerWrapper; ////// Initializes a new System.Data.Services.BaseServiceProvider instance. /// /// Metadata for this provider. /// data service instance. protected BaseServiceProvider(MetadataCacheItem metadata, object dataServiceInstance) { WebUtil.CheckArgumentNull(metadata, "metadata"); WebUtil.CheckArgumentNull(dataServiceInstance, "dataServiceInstance"); this.metadata = metadata; this.dataServiceInstance = dataServiceInstance; } #region IDataServiceQueryProvider Properties ///Returns the instance from which data is provided. public object CurrentDataSource { [DebuggerStepThrough] get { // Many debuggers will try to display this property, and we don't want to trigger an assertion. Debug.Assert( System.Diagnostics.Debugger.IsAttached || this.instance != null, "this.instance != null -- otherwise CurrentDataSource is accessed before initialization or after disposal."); return this.instance; } set { WebUtil.CheckArgumentNull(value, "value"); this.instance = value; } } ///Gets a value indicating whether null propagation is required in expression trees. public abstract bool IsNullPropagationRequired { get; } #endregion IDataServiceQueryProvider Properties #region IDataServiceMetadataProvider Properties ///Namespace name for the EDM container. public abstract string ContainerNamespace { get; } ///Name of the EDM container public abstract string ContainerName { get; } ///Gets all available containers. ///An enumerable object with all available containers. public IEnumerableResourceSets { get { return this.EntitySets.Values; } } /// Returns all the types in this data source public IEnumerableTypes { get { return this.metadata.TypeCache.Values; } } /// Returns all known service operations. public IEnumerableServiceOperations { get { foreach (ServiceOperation serviceOperation in this.metadata.ServiceOperations.Values) { yield return serviceOperation; } } } #endregion IDataServiceMetadataProvider Properties /// EDM version to which metadata is compatible. ////// For example, a service operation of type Void is not acceptable 1.0 CSDL, /// so it should use 1.1 CSDL instead. Similarly, OpenTypes are supported /// in 1.2 and not before. /// internal MetadataEdmSchemaVersion EdmSchemaVersion { get { return this.metadata.EdmSchemaVersion; } } ///Whether all EPM properties serialize in an Astoria V1-compatible way. ////// This property is false if any property has KeepInContent set to false. /// internal bool EpmIsV1Compatible { [DebuggerStepThrough] get { return this.metadata.EpmIsV1Compatible; } } ////// Reference back to the provider wrapper. /// internal DataServiceProviderWrapper ProviderWrapper { set { this.providerWrapper = value; } get { Debug.Assert(this.providerWrapper != null, "this.providerWrapper != null"); return this.providerWrapper; } } ///Returns the list of entity sets. protected IDictionaryEntitySets { [DebuggerStepThrough] get { return this.metadata.EntitySets; } } /// Target type for the data provider protected Type Type { [DebuggerStepThrough] get { return this.metadata.Type; } } ///Cache of resource properties per type. private DictionaryTypeCache { [DebuggerStepThrough] get { return this.metadata.TypeCache; } } /// Cache of immediate derived types per type. private Dictionary> ChildTypesCache { [DebuggerStepThrough] get { return this.metadata.ChildTypesCache; } } #region Public Methods /// Applies expansions and projections to the specified ///. object to expand and apply projections to. /// The root node of the tree which describes /// the projections and expansions to be applied to the . /// /// An ///object, with the results including /// the expansions and projections specified in . /// /// The returned public abstract IQueryable ApplyProjections( IQueryable source, ProjectionNode projection); ///may implement the interface /// to provide enumerable objects for the expansions; otherwise, the expanded /// information is expected to be found directly in the enumerated objects. If paging is /// requested by providing a non-empty list in .OrderingInfo then /// it is expected that the topmost would have a $skiptoken property /// which will be an in itself and each of it's sub-properties will /// be named SkipTokenPropertyXX where XX represents numbers in increasing order starting from 0. Each of /// SkipTokenPropertyXX properties will be used to generated the $skiptoken to support paging. /// If projections are required, the provider may choose to return /// which returns instances of . In that case property values are determined /// by calling the method instead of /// accessing properties of the returned object directly. /// If both expansion and projections are required, the provider may choose to return /// of which in turn returns from its /// property. /// /// Gets the ResourceAssociationSet instance when given the source association end. /// /// Resource set of the source association end. /// Resource type of the source association end. /// Resource property of the source association end. ///ResourceAssociationSet instance. public abstract ResourceAssociationSet GetResourceAssociationSet(ResourceSet resourceSet, ResourceType resourceType, ResourceProperty resourceProperty); ////// Checks whether the specified /// Type to check. ///is ordered. /// true if the type may be ordered; false otherwise. ////// The ordering may still fail at runtime; this method is currently /// used for cleaner error messages only. /// public virtual bool GetTypeIsOrdered(Type type) { Debug.Assert(type != null, "type != null"); return type == typeof(object) || WebUtil.IsPrimitiveType(type); } ////// Returns the requested service /// /// type of service you are requesting for. ///returns the instance of the requested service. public virtual object GetService(Type serviceType) { if (typeof(IDataServiceMetadataProvider) == serviceType || typeof(IDataServiceQueryProvider) == serviceType || typeof(IProjectionProvider) == serviceType) { return this; } return null; } ///Releases the current data source object as necessary. void IDisposable.Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } #endregion Public Methods #region IDataServiceQueryProvider Methods ////// Returns the IQueryable that represents the container. /// /// resource set representing the entity set. ////// An IQueryable that represents the container; null if there is /// no container for the specified name. /// public IQueryable GetQueryRootForResourceSet(ResourceSet container) { Debug.Assert(container != null, "resourceContainer != null"); return this.GetResourceContainerInstance(container); } ///Gets the /// Instance to extract afor the specified . from. /// The public ResourceType GetResourceType(object resource) { Debug.Assert(resource != null, "instance != null"); return this.GetNonPrimitiveType(resource.GetType()); } ///that describes this in this provider. /// Get the value of the strongly typed property. /// /// instance of the type declaring the property. /// resource property describing the property. ///value for the property. public object GetPropertyValue(object target, ResourceProperty resourceProperty) { Debug.Assert(target != null, "target != null"); Debug.Assert(resourceProperty != null, "resourceProperty != null"); try { PropertyInfo propertyInfo = this.GetResourceType(target).GetPropertyInfo(resourceProperty); Debug.Assert(propertyInfo != null, "propertyInfo != null"); return propertyInfo.GetGetMethod().Invoke(target, null); } catch (TargetInvocationException exception) { ErrorHandler.HandleTargetInvocationException(exception); throw; } } ////// Gets the value of the open property. /// /// instance of the resource type. /// name of the property. ///the value of the open property. If the property is not present, return null. public abstract object GetOpenPropertyValue(object target, string propertyName); ////// Get the name and values of all the properties defined in the given instance of an open type. /// /// instance of a open type. ///collection of name and values of all the open properties. public abstract IEnumerable> GetOpenPropertyValues(object target); /// /// Invoke the given service operation instance. /// /// metadata for the service operation to invoke. /// list of parameters to pass to the service operation. ///returns the result by the service operation instance. public object InvokeServiceOperation(ServiceOperation serviceOperation, object[] parameters) { return ((MethodInfo)serviceOperation.CustomState).Invoke( this.dataServiceInstance, BindingFlags.Instance | BindingFlags.Instance | BindingFlags.FlattenHierarchy, null, parameters, Globalization.CultureInfo.InvariantCulture); } #endregion IDataServiceQueryProvider Methods #region IDataServiceMetadataProvider Methods ////// The method must return a collection of all the types derived from /// Resource to get derived resource types from. ///. /// The collection returned should NOT include the type passed in as a parameter. /// An implementer of the interface should return null if the type does not have any derived types (ie. null == no derived types). /// /// A collection of resource types ( public IEnumerable) derived from the specified /// or null if there no types derived from the specified exist. /// GetDerivedTypes(ResourceType resourceType) { Debug.Assert(resourceType != null, "resourceType != null"); Debug.Assert(this.ChildTypesCache.ContainsKey(resourceType), "this.ChildTypesCache.ContainsKey(resourceType)"); List childTypes = this.ChildTypesCache[resourceType]; if (childTypes != null) { foreach (ResourceType childType in childTypes) { yield return childType; foreach (ResourceType descendantType in this.GetDerivedTypes(childType)) { yield return descendantType; } } } } /// /// Returns true if /// instance of the resource type in question. ///represents an Entity Type which has derived Entity Types, else false. /// True if public bool HasDerivedTypes(ResourceType resourceType) { Debug.Assert(resourceType != null, "resourceType != null"); Debug.Assert(this.ChildTypesCache.ContainsKey(resourceType), "this.ChildTypesCache.ContainsKey(resourceType)"); Debug.Assert(this.ChildTypesCache[resourceType] == null || this.ChildTypesCache[resourceType].Count > 0, "this.ChildTypesCache[resourceType] == null || this.ChildTypesCache[resourceType].Count > 0"); return this.ChildTypesCache[resourceType] != null; } ///represents an Entity Type which has derived Entity Types, else false. Given the specified name, tries to find a resource set. /// Name of the resource set to resolve. /// Returns the resolved resource set, null if no resource set for the given name was found. ///True if resource set with the given name was found, false otherwise. public bool TryResolveResourceSet(string name, out ResourceSet resourceSet) { Debug.Assert(!string.IsNullOrEmpty(name), "!string.IsNullOrEmpty(name)"); return this.EntitySets.TryGetValue(name, out resourceSet); } ///Given the specified name, tries to find a service operation. /// Name of the service operation to resolve. /// Returns the resolved service operation, null if no service operation was found for the given name. ///True if we found the service operation for the given name, false otherwise. public bool TryResolveServiceOperation(string name, out ServiceOperation serviceOperation) { Debug.Assert(!string.IsNullOrEmpty(name), "!string.IsNullOrEmpty(name)"); return this.metadata.ServiceOperations.TryGetValue(name, out serviceOperation); } ///Given the specified name, tries to find a type. /// Name of the type to resolve. /// Returns the resolved resource type, null if no resource type for the given name was found. ///True if we found the resource type for the given name, false otherwise. public bool TryResolveResourceType(string name, out ResourceType resourceType) { Debug.Assert(!string.IsNullOrEmpty(name), "!string.IsNullOrEmpty(name)"); Debug.Assert(this.metadata != null, "this.metadata != null"); Debug.Assert(this.TypeCache != null, "this.TypeCache != null"); foreach (ResourceType t in this.TypeCache.Values) { if (t.FullName == name) { resourceType = t; return true; } } resourceType = null; return false; } #endregion IDataServiceMetadataProvider Methods #region Internal Methods ////// Returns the type of the IEnumerable if the type implements IEnumerable interface; null otherwise. /// /// type that needs to be checked ///Element type if the type implements IEnumerable, else returns null internal static Type GetIEnumerableElement(Type type) { return GetGenericInterfaceElementType(type, IEnumerableTypeFilter); } ////// Returns the "T" in the IQueryable of T implementation of type. /// /// Type to check. /// filter against which the type is checked ////// The element type for the generic IQueryable interface of the type, /// or null if it has none or if it's ambiguous. /// internal static Type GetGenericInterfaceElementType(Type type, TypeFilter typeFilter) { Debug.Assert(type != null, "type != null"); Debug.Assert(!type.IsGenericTypeDefinition, "!type.IsGenericTypeDefinition"); if (typeFilter(type, null)) { return type.GetGenericArguments()[0]; } Type[] queriables = type.FindInterfaces(typeFilter, null); if (queriables != null && queriables.Length == 1) { return queriables[0].GetGenericArguments()[0]; } else { return null; } } ////// Checks whether the provider implements IUpdatable. /// ///returns true if the provider implements IUpdatable. otherwise returns false. internal abstract bool ImplementsIUpdatable(); ///Adds service operations based on methods of the specified type. /// Type with methods to add. internal void AddOperationsFromType(Type type) { Debug.Assert(type != null, "type != null"); foreach (MethodInfo methodInfo in type.GetMethods(WebUtil.PublicInstanceBindingFlags | BindingFlags.FlattenHierarchy)) { if (methodInfo.GetCustomAttributes(typeof(WebGetAttribute), true).Length != 0) { this.AddServiceOperation(methodInfo, XmlConstants.HttpMethodGet); } else if (methodInfo.GetCustomAttributes(typeof(WebInvokeAttribute), true).Length != 0) { this.AddServiceOperation(methodInfo, XmlConstants.HttpMethodPost); } } } ///Populates the metadata for the given provider. internal void PopulateMetadata() { Debug.Assert(this.metadata != null, "this.metadata != null -- otherwise we don't have an item to populate"); this.PopulateMetadata(this.TypeCache, this.ChildTypesCache, this.EntitySets); } ////// Applies access rights to entity sets /// /// Data service configuration instance with access right info. internal void ApplyConfiguration(DataServiceConfiguration configuration) { Debug.Assert(configuration != null, "configuration != null"); this.PopulateMetadataForUserSpecifiedTypes(configuration.GetKnownTypes(), this.TypeCache, this.ChildTypesCache, this.EntitySets.Values); this.CheckConfigurationConsistency(this.instance, configuration); } ///Make all the metadata readonly internal void MakeMetadataReadonly() { foreach (ResourceSet container in this.ResourceSets) { container.SetReadOnly(); } foreach (ResourceType resourceType in this.Types) { resourceType.SetReadOnly(); if (!resourceType.EpmIsV1Compatible) { this.metadata.EpmIsV1Compatible = false; } } foreach (ServiceOperation operation in this.ServiceOperations) { operation.SetReadOnly(); } } #endregion Internal Methods #region Protected methods. ////// Returns the type of the IQueryable if the type implements IQueryable interface /// /// clr type on which IQueryable check needs to be performed. ///Element type if the property type implements IQueryable, else returns null protected static Type GetIQueryableElement(Type type) { return GetGenericInterfaceElementType(type, IQueryableTypeFilter); } ////// Find the corresponding ResourceType for a given Type, primitive or not /// /// Non-primitive types to search /// Type to look for /// Corresponding ResourceType, if found ///True if type found, false otherwise protected static bool TryGetType(IDictionaryknownTypes, Type type, out ResourceType resourceType) { Debug.Assert(knownTypes != null, "knownTypes != null"); Debug.Assert(type != null, "type != null"); resourceType = ResourceType.GetPrimitiveResourceType(type); if (resourceType == null) { knownTypes.TryGetValue(type, out resourceType); } return resourceType != null; } /// Checks that the applied configuration is consistent. /// Instance of the data source for the provider. /// Data service configuration instance with access right info. ///At this point in initialization, metadata trimming hasn't taken place. protected virtual void CheckConfigurationConsistency(object dataSourceInstance, DataServiceConfiguration configuration) { } ///Releases the current data source object as necessary. /// /// Whether this method is called from an explicit call to Dispose by /// the consumer, rather than during finalization. /// protected virtual void Dispose(bool disposing) { WebUtil.Dispose(this.instance); this.instance = null; } ////// Returns the resource type of the given instance and validates that the instance returns a single resource. /// /// clr instance of a resource. ///resource type of the given instance. protected ResourceType GetSingleResource(object resource) { ResourceType resourceType = this.ProviderWrapper.GetResourceType(resource); return resourceType; } ////// Creates the object query for the given resource set and returns it /// /// resource set for which IQueryable instance needs to be created ///returns the IQueryable instance for the given resource set protected abstract IQueryable GetResourceContainerInstance(ResourceSet resourceContainer); ////// Populates the metadata for the given provider /// /// list of known types /// list of known types and their immediate children /// list of entity sets protected abstract void PopulateMetadata( IDictionaryknownTypes, IDictionary > childTypes, IDictionary entitySets); /// /// Populate types for metadata specified by the provider /// /// list of types specified by the provider /// list of already known types /// list of already known types and their immediate children /// list of entity sets as specified in the data source type protected abstract void PopulateMetadataForUserSpecifiedTypes(IEnumerableuserSpecifiedTypes, IDictionary knownTypes, IDictionary > childTypes, IEnumerable entitySets); /// /// Populate metadata for the given clr type. /// /// type whose metadata needs to be loaded. /// list of already known resource types. /// list of already known types and their immediate children /// list of entity sets as specified in the data source. ///resource type containing metadata for the given clr type. protected abstract ResourceType PopulateMetadataForType(Type type, IDictionaryknownTypes, IDictionary > childTypes, IEnumerable entitySets); #endregion Protected methods. #region Private Methods /// Filter callback for finding IQueryable implementations. /// Type to inspect. /// Filter criteria. ///true if the specified type is an IQueryable of T; false otherwise. private static bool IQueryableTypeFilter(Type m, object filterCriteria) { Debug.Assert(m != null, "m != null"); return m.IsGenericType && m.GetGenericTypeDefinition() == typeof(IQueryable<>); } ///Filter callback for finding IEnumerable implementations. /// Type to inspect. /// Filter criteria. ///true if the specified type is an IEnumerable of T; false otherwise. private static bool IEnumerableTypeFilter(Type m, object filterCriteria) { Debug.Assert(m != null, "m != null"); return m.IsGenericType && m.GetGenericTypeDefinition() == typeof(IEnumerable<>); } ///Updates the EDM schema version if it is currently lower than /// New version for EDM schema. private void UpdateEdmSchemaVersion(MetadataEdmSchemaVersion newVersion) { if (this.metadata.EdmSchemaVersion < newVersion) { this.metadata.EdmSchemaVersion = newVersion; } } ///. /// Adds a new /// Method to expose as a service operation. /// Protocol (for example HTTP) method the service operation responds to. 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); } ///based on the specified /// instance. /// /// 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. /// /// clrType whose corresponding resource type needs to be returned ///Returns the resource type private ResourceType GetNonPrimitiveType(Type type) { Debug.Assert(type != null, "type != null"); // Check for the type directly first ResourceType resourceType; if (this.TypeCache.TryGetValue(type, out resourceType)) { return resourceType; } // check for ienumerable types Type elementType = BaseServiceProvider.GetIEnumerableElement(type); if (elementType != null) { resourceType = ResourceType.GetPrimitiveResourceType(elementType); if (resourceType == null) { this.TypeCache.TryGetValue(elementType, out resourceType); } } return resourceType; } ////// Looks for the first resource set that the specified /// Type to look for. /// After the method returns, the container to which the type could belong. ////// could belong to. /// true if a container was found; false otherwise. private bool TryFindAnyContainerForType(ResourceType type, out ResourceSet container) { Debug.Assert(type != null, "type != null"); foreach (ResourceSet c in this.EntitySets.Values) { if (c.ResourceType.IsAssignableFrom(type)) { container = c; return true; } } container = default(ResourceSet); return false; } #endregion Private Methods #region QueryableOverEnumerable #if DEBUG ///Implementation of the ///interface which only support /// the enumerable portion of the interface. Used for the old internal class QueryableOverEnumerable : IQueryable { ///which returns /// but we require instead. The private readonly IEnumerable enumerable; ///this object wraps. Constructor - creates new instance. /// Theto wrap with . internal QueryableOverEnumerable(IEnumerable enumerable) { this.enumerable = enumerable; } /// The type of the element - not implemented as nothing should call this. public Type ElementType { get { throw new NotImplementedException(); } } ///The expression for the query - not implemented as nothing should call this. public System.Linq.Expressions.Expression Expression { get { throw new NotImplementedException(); } } ///The query provider for this query - not implemented as nothing should call this. public IQueryProvider Provider { get { throw new NotImplementedException(); } } ///Creates new enumerator of the results of this query. ///New public IEnumerator GetEnumerator() { return this.enumerable.GetEnumerator(); } } #endif #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.to enumerate results of this query.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- WizardStepBase.cs
- Baml6Assembly.cs
- WorkflowPersistenceService.cs
- autovalidator.cs
- FormViewAutoFormat.cs
- PageStatePersister.cs
- CatalogPartCollection.cs
- XmlReflectionImporter.cs
- HandlerWithFactory.cs
- SystemResourceHost.cs
- DesignerRegion.cs
- PeerNearMe.cs
- DataMemberConverter.cs
- AmbiguousMatchException.cs
- ObjectIDGenerator.cs
- FlagPanel.cs
- DocumentDesigner.cs
- DBDataPermission.cs
- Solver.cs
- XmlElementElement.cs
- DebugView.cs
- DoubleAnimation.cs
- SqlCacheDependencyDatabase.cs
- ColorIndependentAnimationStorage.cs
- HtmlHistory.cs
- odbcmetadatacollectionnames.cs
- StringBuilder.cs
- BitmapDownload.cs
- InputElement.cs
- WrappedIUnknown.cs
- RelationshipDetailsCollection.cs
- MetaTable.cs
- TextRange.cs
- IPAddressCollection.cs
- TemplatedAdorner.cs
- XmlCharacterData.cs
- HttpListenerRequest.cs
- KeyValuePair.cs
- LinkLabel.cs
- XmlNamespaceManager.cs
- Pen.cs
- CollectionType.cs
- Floater.cs
- SQLDecimal.cs
- DesignerActionPropertyItem.cs
- PolyBezierSegment.cs
- UIElementCollection.cs
- NonParentingControl.cs
- IdnMapping.cs
- oledbconnectionstring.cs
- AutomationPatternInfo.cs
- bindurihelper.cs
- ReadOnlyDataSourceView.cs
- KeyGesture.cs
- CapacityStreamGeometryContext.cs
- ObfuscateAssemblyAttribute.cs
- Misc.cs
- MetadataArtifactLoaderComposite.cs
- SchemaCollectionCompiler.cs
- FileRecordSequenceCompletedAsyncResult.cs
- ActivityValidationServices.cs
- XPathNavigator.cs
- WebScriptClientGenerator.cs
- ColorKeyFrameCollection.cs
- PersonalizationStateQuery.cs
- ViewCellRelation.cs
- XamlTypeMapperSchemaContext.cs
- Menu.cs
- SqlTypeSystemProvider.cs
- DecimalStorage.cs
- ClientUtils.cs
- CodeExpressionCollection.cs
- RadialGradientBrush.cs
- IncrementalCompileAnalyzer.cs
- ConsoleKeyInfo.cs
- XmlProcessingInstruction.cs
- Point3DAnimationUsingKeyFrames.cs
- PrintDialog.cs
- IBuiltInEvidence.cs
- ImageListDesigner.cs
- UrlPath.cs
- CodeNamespaceImportCollection.cs
- TraceHwndHost.cs
- Mutex.cs
- BinarySecretSecurityToken.cs
- StylusDevice.cs
- Compiler.cs
- NetCodeGroup.cs
- IdentityHolder.cs
- Zone.cs
- ControlEvent.cs
- FieldInfo.cs
- LookupBindingPropertiesAttribute.cs
- _SslStream.cs
- DragSelectionMessageFilter.cs
- XamlSerializerUtil.cs
- ListViewInsertEventArgs.cs
- CompoundFileIOPermission.cs
- OpCellTreeNode.cs
- QilList.cs