Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataWeb / Server / System / Data / Services / Providers / BaseServiceProvider.cs / 1 / 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; using System.Xml; #endregion Namespaces. ///Provides a reflection-based internal abstract class BaseServiceProvider : IDataServiceProvider, IDisposable, IUpdatable, IExpandProvider { ///implementation. 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; ////// Initializes a new System.Data.Services.BaseServiceProvider instance. /// /// Metadata for this provider. /// instance of the data source provider. protected BaseServiceProvider(MetadataCacheItem metadata, object dataSourceInstance) { WebUtil.CheckArgumentNull(metadata, "metadata"); WebUtil.CheckArgumentNull(dataSourceInstance, "dataSourceInstance"); this.metadata = metadata; this.instance = dataSourceInstance; } ///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; } } ///Gets a value indicating whether null propagation is required in expression trees. public abstract bool NullPropagationRequired { get; } ////// Provides a name for the context in which all resource containers are. /// public abstract string ResourceContextName { get; } ///Returns the list of entity sets. protected IDictionaryEntitySets { [DebuggerStepThrough] get { return this.metadata.EntitySets; } } /// Returns all known service operations. protected IEnumerableServiceOperations { [DebuggerStepThrough] get { return this.metadata.ServiceOperations.Values; } } /// Target type for the data provider protected Type Type { [DebuggerStepThrough] get { return this.metadata.Type; } } ///Returns the list of resource types. protected IEnumerableTypes { [DebuggerStepThrough] get { return this.metadata.TypeCache.Values; } } /// Returns true if the metadata is compatible with Edm V1 Schema otherwise false protected bool CompatibleWithV1Schema { get { return this.metadata.EdmVersion1Schema; } } ///Cache of resource properties per type. private DictionaryTypeCache { [DebuggerStepThrough] get { return this.metadata.TypeCache; } } /// Applies expansions to the specified ///. object to expand. /// A collection of ordered paths. /// /// An ///object of the same type as the given , /// with the results including the specified . /// /// This method may modify the public abstract IEnumerable ApplyExpansions(IQueryable queryable, ICollectionto indicate which expansions /// are included. /// /// The returned 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. /// expandPaths); /// /// Get the container name corresponding to the given navigation property /// The declaring type container name refers to the entity set that the declaring type belongs to /// /// name of the entity container that the declaring type belongs to /// declaring type /// resource navigation property ///name of the container that this property refers to public abstract ResourceContainer GetContainer(string declaringTypeContainerName, Type declaringResourceType, ResourceProperty resourceProperty); ///Gets the name of the container that holds this resource type. This method is called for open types only /// Resource to get container for. ////// The name of the container for the specified resource; null if it cannot /// be determined. /// public abstract ResourceContainer GetContainerForResourceType(Type resourceType); ///Gets the metadata document for this provider. /// Writer to which metadata XML should be written. public abstract void GetMetadata(XmlWriter writer); ////// Get the list of property names that form the ETag for the given resource instance /// /// name of the container to which the resource belongs t /// clr type of the resource whose etag properties need to be fetched ///list of property names that form the ETag for the given resource instance public abstract ICollectionGetETagProperties(string containerName, Type resourceClrType); #region IUpdatable Members /// /// Creates the resource of the given type and belonging to the given container /// /// container name to which the resource needs to be added /// full type name i.e. Namespace qualified type name of the resource ///object representing a resource of given type and belonging to the given container public abstract object CreateResource(string containerName, string fullTypeName); ////// Gets the resource of the given type that the query points to /// /// query pointing to a particular resource /// full type name i.e. Namespace qualified type name of the resource ///object representing a resource of given type and as referenced by the query public abstract object GetResource(IQueryable query, string fullTypeName); ////// 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); } ////// Resets the value of the given resource to its default value /// /// resource whose value needs to be reset ///same resource with its value reset public abstract object ResetResource(object resource); ////// Sets the value of the given property on the target object /// /// target object which defines the property /// name of the property whose value needs to be updated /// value of the property public abstract void SetValue(object targetResource, string propertyName, object propertyValue); ////// Gets the value of the given property on the target object /// /// target object which defines the property /// name of the property whose value needs to be updated ///the value of the property for the given target resource public abstract object GetValue(object targetResource, string propertyName); ////// Sets the value of the given reference property on the target object /// /// target object which defines the property /// name of the property whose value needs to be updated /// value of the property public abstract void SetReference(object targetResource, string propertyName, object propertyValue); ////// Adds the given value to the collection /// /// target object which defines the property /// name of the property whose value needs to be updated /// value of the property which needs to be added public abstract void AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded); ////// Removes the given value from the collection /// /// target object which defines the property /// name of the property whose value needs to be updated /// value of the property which needs to be removed public abstract void RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved); ////// Delete the given resource /// /// resource that needs to be deleted public abstract void DeleteResource(object targetResource); ////// Saves all the pending changes made till now /// public abstract void SaveChanges(); ////// Returns the actual instance of the resource represented by the given resource object /// /// object representing the resource whose instance needs to be fetched ///The actual instance of the resource represented by the given resource object public abstract object ResolveResource(object resource); ////// Revert all the pending changes. /// public abstract void ClearChanges(); #endregion #region IDataServiceProvider Members ////// Applies the settings specified in the given /// Configuration to apply. /// Instance of the data source for the provider. void IDataServiceProvider.ApplyConfiguration(DataServiceConfiguration configuration, object dataSourceInstance) { Debug.Assert(configuration != null, "configuration != null"); this.PopulateMetadataForUserSpecifiedTypes(configuration.GetKnownTypes(), this.TypeCache, this.EntitySets.Values); this.ApplyRights(configuration); this.CheckConfigurationConsistency(dataSourceInstance); this.RemoveHiddenResourceContainers(); this.RemoveHiddenServiceOperations(); this.RemoveHiddenProperties(); this.RemoveHiddenTypes(); this.CheckServiceOperationContainers(); this.DisallowDerivedEntityTypesWithNavProperties(); } ///. /// Disposes of the underlying void IDataServiceProvider.DisposeDataSource() { WebUtil.Dispose(this.instance); this.instance = null; } ///. Gets all available containers. ///An enumerable object with all available containers. IEnumerableIDataServiceProvider.GetContainers() { return this.EntitySets.Values; } /// /// Returns the IQueryable that represents the container. /// /// Name of the resource container. ////// An IQueryable that represents the container; null if there is /// no container for the specified name. /// IQueryable IDataServiceProvider.ResolveContainerName(string containerName) { ResourceContainer resourceContainer = ((IDataServiceProvider)this).TryResolveContainerName(containerName); if (resourceContainer != null) { return this.GetResourceContainerInstance(resourceContainer); } else { return null; } } ///Gets the root type of the given resource type. /// ResourceType to get least derived type for. ///The least derived type for the specified ResourceType IDataServiceProvider.GetRootType(ResourceType resourceType) { if (resourceType == null) { return resourceType; } while (resourceType.BaseType != null) { resourceType = resourceType.BaseType; } return resourceType; } ///. Gets the ///for the specified . to map into a . /// The ResourceType IDataServiceProvider.GetResourceType(Type type) { Debug.Assert(type != null, "type != null"); return this.GetType(type); } ///that maps to for this provider. Gets the kind of resource that the type is. ///to check. /// The kind of resource that the specified ResourceTypeKind IDataServiceProvider.GetResourceTypeKind(Type type) { Debug.Assert(type != null, "type != null"); ResourceType resourceType = this.GetType(type); Debug.Assert(resourceType != null, "resourceType != null -- otherwise the specified Type '" + type + "' isn't part of the known type system."); return resourceType.ResourceTypeKind; } ///is. Given the specified name, tries to find a resource container. /// Name of the resource container to resolve. ///Resolved resource container, possibly null. ResourceContainer IDataServiceProvider.TryResolveContainerName(string name) { ResourceContainer resourceContainer; if (this.EntitySets.TryGetValue(name, out resourceContainer)) { return resourceContainer; } else { return null; } } ///Given the specified CLR type, finds the named property. /// Type to get property for. /// Name of property to resolve. ///Resolved property, possibly null. ////// ResourceProperty IDataServiceProvider.TryResolvePropertyName(Type type, string propertyName) { Debug.Assert(type != null, "type != null"); Debug.Assert(propertyName != null, "propertyName != null"); // Look for a known type. ResourceType resourceType; if (this.TypeCache.TryGetValue(type, out resourceType)) { return resourceType.TryResolvePropertyName(propertyName); } // The property wasn't found. return null; } ///should be a resource type or a complex type. /// Given the specified name, tries to find a service operation. /// Name of the service operation to resolve. ///Resolved operation, possibly null. ServiceOperation IDataServiceProvider.TryResolveServiceOperation(string name) { Debug.Assert(name != null, "name != null"); ServiceOperation result; if (this.metadata.ServiceOperations.TryGetValue(name, out result)) { return result; } else { return null; } } ///Given the specified name, tries to find a type. /// Name of the type to resolve. ///Resolved resource type, possibly null. ResourceType IDataServiceProvider.TryResolveTypeName(string name) { Debug.Assert(name != null, "name != null"); 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) { return t; } } return null; } #endregion //IDataServiceProvider Members ///Releases the current data source object as necessary. void IDisposable.Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } ////// 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; } } ///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, false); } else if (methodInfo.GetCustomAttributes(typeof(WebInvokeAttribute), true).Length != 0) { this.AddServiceOperation(methodInfo, true); } } } ///Populates the metadata for the given provider. internal void PopulateMetadata() { // Add the primitive types to the type cache. foreach (ResourceType resourceType in WebUtil.GetPrimitiveTypes()) { this.TypeCache.Add(resourceType.Type, resourceType); } this.PopulateMetadata(this.TypeCache, this.EntitySets); #if ASTORIA_CONTAINMENT this.ApplyAccessPaths(); #endif } #region Protected methods. ////// Writes the edmx elements for the metadata document. /// /// xml writer into which the metadata document needs to be written. protected static void WriteTopLevelSchemaElements(XmlWriter writer) { writer.WriteStartElement(XmlConstants.EdmxNamespacePrefix, XmlConstants.EdmxElement, XmlConstants.EdmxNamespace); writer.WriteAttributeString(XmlConstants.EdmxVersion, XmlConstants.EdmxVersionValue); writer.WriteStartElement(XmlConstants.EdmxNamespacePrefix, XmlConstants.EdmxDataServicesElement, XmlConstants.EdmxNamespace); } ////// Writes the lop level schema element /// /// xml writer into which the schema node definition is written to /// namespace of the schema /// true if the metadata is compatible with the edm v1 schema protected static void WriteSchemaElement(XmlWriter writer, string schemaNamespace, bool compatibleWithV1Schema) { if (compatibleWithV1Schema) { writer.WriteStartElement(XmlConstants.Schema, XmlConstants.EdmV1Namespace); } else { writer.WriteStartElement(XmlConstants.Schema, XmlConstants.EdmV2Namespace); } writer.WriteAttributeString(XmlConstants.Namespace, schemaNamespace); writer.WriteAttributeString(XmlConstants.XmlnsNamespacePrefix, XmlConstants.DataWebNamespacePrefix, null, XmlConstants.DataWebNamespace); writer.WriteAttributeString(XmlConstants.XmlnsNamespacePrefix, XmlConstants.DataWebMetadataNamespacePrefix, null, XmlConstants.DataWebMetadataNamespace); } ////// 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); } ///Writes an attribute in the dataweb metadata namespace. /// XmlWriter in which the attribute needs to be written /// Attribute name. /// Attribute value. protected static void WriteDataWebMetadata(XmlWriter writer, string name, string value) { Debug.Assert(writer != null, "writer != null"); Debug.Assert(name != null, "name != null"); Debug.Assert(value != null, "value != null"); writer.WriteAttributeString(XmlConstants.DataWebMetadataNamespacePrefix, name, XmlConstants.DataWebMetadataNamespace, value); } ///Checks that the applied configuration is consistent. /// Instance of the data source for the provider. ///At this point in initialization, metadata trimming hasn't taken place. protected virtual void CheckConfigurationConsistency(object dataSourceInstance) { } ///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) { ((IDataServiceProvider)this).DisposeDataSource(); } #if ASTORIA_CONTAINMENT ////// Returns an object that can enumerate all ////// instances that apply to this model. /// /// An object that can enumerate all protected abstract IEnumerable/// instances that apply to this model. /// EnumerateAccessPathAttributes(); #endif /// /// Writes the service operations as FunctionImports in the specified /// Writer to which CSDL is being written to. /// Enumeration of service operations to be written. protected void WriteServiceOperations( XmlWriter writer, IEnumerable. /// serviceOperations) { Debug.Assert(writer != null, "writer != null"); foreach (ServiceOperation operation in serviceOperations) { string returnTypeString; string entitySetName = null; if (operation.ResultKind == ServiceOperationResultKind.Nothing) { returnTypeString = null; } else { ResourceType resourceType = ((IDataServiceProvider)this).GetResourceType(operation.ResultType); returnTypeString = resourceType.FullName; if (resourceType.ResourceTypeKind == ResourceTypeKind.EntityType) { ResourceContainer container = operation.EntitySet; Debug.Assert( container != null, "this.TryFindAnyContainerForType(operation.ResultType, out container) -- otherwise, we didn't trim operation '" + operation.Name + "' based on its type having no container."); entitySetName = container.Name; } if (operation.ResultKind != ServiceOperationResultKind.QueryWithSingleResult && operation.ResultKind != ServiceOperationResultKind.DirectValue) { Debug.Assert( operation.ResultKind == ServiceOperationResultKind.Enumeration || operation.ResultKind == ServiceOperationResultKind.QueryWithMultipleResults, operation.ResultKind + " == Enumeration or QueryWithMultipleResults"); returnTypeString = String.Format(CultureInfo.InvariantCulture, XmlConstants.EdmCollectionTypeFormat, returnTypeString); } } writer.WriteStartElement(XmlConstants.EdmFunctionImportElementName); writer.WriteAttributeString(XmlConstants.Name, operation.Name); if (entitySetName != null) { writer.WriteAttributeString(XmlConstants.EdmEntitySetAttributeName, entitySetName); } if (returnTypeString != null) { writer.WriteAttributeString(XmlConstants.EdmReturnTypeAttributeName, returnTypeString); } string verb = operation.Invoke ? XmlConstants.HttpMethodPost : XmlConstants.HttpMethodGet; BaseServiceProvider.WriteDataWebMetadata(writer, XmlConstants.ServiceOperationHttpMethodName, verb); if (!String.IsNullOrEmpty(operation.MimeType)) { BaseServiceProvider.WriteDataWebMetadata(writer, XmlConstants.DataWebMimeTypeAttributeName, operation.MimeType); } foreach (ServiceOperationParameter parameter in operation.Parameters) { writer.WriteStartElement(XmlConstants.EdmParameterElementName); writer.WriteAttributeString(XmlConstants.Name, parameter.Name); writer.WriteAttributeString(XmlConstants.Type, WebUtil.GetEdmTypeName(parameter.Type)); writer.WriteAttributeString(XmlConstants.EdmModeAttributeName, XmlConstants.EdmModeInValue); writer.WriteEndElement(); } writer.WriteEndElement(); } } /// /// Creates the object query for the given resource container and returns it /// /// resource container for which IQueryable instance needs to be created ///returns the IQueryable instance for the given resource container protected abstract IQueryable GetResourceContainerInstance(ResourceContainer resourceContainer); ////// Populates the metadata for the given provider /// /// list of known types /// list of entity sets protected abstract void PopulateMetadata( IDictionaryknownTypes, IDictionary entitySets); /// /// Populate types for metadata specified by the provider /// /// list of types specified by the provider /// list of already known types /// list of entity sets as specified in the data source type protected abstract void PopulateMetadataForUserSpecifiedTypes(IEnumerableuserSpecifiedTypes, IDictionary knownTypes, IEnumerable entitySets); /// /// Populate metadata for the given clr type. /// /// type whose metadata needs to be loaded. /// list of already known resource types. /// 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, IEnumerable entitySets); #endregion Protected 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<>); } ////// Removes the entries from ///in the /// specified . /// Type of dictionary key to remove. ///Type of dictionary value to remove. /// Dictionary from which entries should be removed. /// Keys for entries to remove from. private static void RemoveKeys (IDictionary dictionary, IEnumerable keys) { Debug.Assert(dictionary != null, "dictionary != null"); Debug.Assert(keys != null, "keys != null"); foreach (TKey key in keys) { bool removed = dictionary.Remove(key); Debug.Assert(removed, "removed - key " + key.ToString() + " should be present."); } } /// /// Marks complex types from the specified /// Set of types that have been marked. /// Types that need to be examined further. /// Type with properties to mark. private static void MarkComplexTypes(HashSet/// by adding them to the given , /// and adding them to the /// to be examined later if this is the first time they are seen. /// markedTypes, Stack pendingTypes, ResourceType type) { foreach (ResourceProperty property in type.Properties) { if (property.TypeKind == ResourceTypeKind.ComplexType) { Debug.Assert(property.ResourceType != null, "property.ResourceType != null"); Debug.Assert(property.ResourceType.ResourceTypeKind == ResourceTypeKind.ComplexType, "property.ResourceType.ResourceTypeKind == ResourceTypeKind.ComplexType"); bool added = markedTypes.Add(property.ResourceType); if (added) { pendingTypes.Push(property.ResourceType); } } } } /// /// Adds a new /// Method to expose as a service operation. /// Whether invocation is required. private void AddServiceOperation(MethodInfo method, bool invoke) { Debug.Assert(method != null, "method != null"); Debug.Assert(!method.IsAbstract, "!method.IsAbstract - if method is abstract, the type is abstract - already checked"); if (this.metadata.ServiceOperations.ContainsKey(method.Name)) { throw new InvalidOperationException(Strings.BaseServiceProvider_OverloadingNotSupported(this.Type, method)); } bool hasSingleResult = SingleResultAttribute.MethodHasSingleResult(method); ServiceOperationResultKind resultKind; Type resultType; ResourceType resourceType; if (method.ReturnType == typeof(void)) { resultKind = ServiceOperationResultKind.Nothing; resultType = typeof(void); resourceType = null; this.metadata.EdmVersion1Schema = false; } else { resourceType = this.GetType(method.ReturnType); if (resourceType != null) { resultKind = ServiceOperationResultKind.DirectValue; resultType = method.ReturnType; this.metadata.EdmVersion1Schema = false; } 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) { if (hasSingleResult) { throw new InvalidOperationException(Strings.BaseServiceProvider_IEnumerableAlwaysMultiple(this.Type, method)); } resultKind = ServiceOperationResultKind.Enumeration; resultType = enumerableElement; } else { resultType = method.ReturnType; resultKind = ServiceOperationResultKind.DirectValue; this.metadata.EdmVersion1Schema = false; } } resourceType = this.PopulateMetadataForType(resultType, this.TypeCache, this.EntitySets.Values); if (resourceType == null) { throw new InvalidOperationException(Strings.BaseServiceProvider_UnsupportedReturnType(method, method.ReturnType)); } if (hasSingleResult || (!hasSingleResult && (resourceType.ResourceTypeKind == ResourceTypeKind.ComplexType || resourceType.ResourceTypeKind == ResourceTypeKind.Primitive))) { this.metadata.EdmVersion1Schema = false; } } } string mimeType = MimeTypeAttribute.GetMemberMimeType(method); ParameterInfo[] parametersInfo = method.GetParameters(); ServiceOperationParameter[] parameters = new ServiceOperationParameter[parametersInfo.Length]; for (int i = 0; i < parameters.Length; i++) { if (parametersInfo[i].IsOut || parametersInfo[i].IsRetval) { throw new InvalidOperationException(Strings.BaseServiceProvider_ParameterNotIn(method, parametersInfo[i])); } if (!WebUtil.IsPrimitiveType(parametersInfo[i].ParameterType)) { throw new InvalidOperationException( Strings.BaseServiceProvider_ParameterTypeNotSupported(method, parametersInfo[i], parametersInfo[i].ParameterType)); } string parameterName = parametersInfo[i].Name ?? "p" + i.ToString(CultureInfo.InvariantCulture); parameters[i] = new ServiceOperationParameter(parameterName, parametersInfo[i].ParameterType); } ServiceOperation operation = new ServiceOperation(method, resultKind, resultType, mimeType, invoke, parameters); this.metadata.ServiceOperations.Add(method.Name, operation); if (resourceType != null && resourceType.ResourceTypeKind == ResourceTypeKind.EntityType) { operation.EntitySet = this.TryFindSingleContainerForType(resultType); if (operation.EntitySet == null) { throw new InvalidOperationException( Strings.BaseServiceProvider_ServiceOperationMissingSingleEntitySet(method, resourceType.FullName)); } } } #if ASTORIA_CONTAINMENT ///based on the specified /// instance. /// Applies access path attributes to the model. private void ApplyAccessPaths() { foreach (AccessPathAttribute path in this.EnumerateAccessPathAttributes()) { Debug.Assert(path != null, "path != null -- otherwise EnumerateAccessPathAttributes is incorrect."); Debug.Assert( path.AnnotatedContainer != null, "path.AnnotatedContainer -- otherwise EnumerateAccessPathAttributes is incorrect."); // When an access path is inferred from schema, full validation hasn't taken place. Validation // errors for inferred values from here on should be ignored, with the result that the proposed // access path doesn't take effect. Exception exception = path.Validate(this); if (exception != null) { if (path.InferredFromSchema) { continue; } else { throw exception; } } // Mark the NavigationProperty with the appropriate values. IDataServiceProvider provider = (IDataServiceProvider)this; ResourceContainer child = path.AnnotatedContainer; ResourceContainer parent = provider.TryResolveContainerName(path.Parent); ResourceProperty parentProperty = parent.ResourceType.TryResolvePropertyName(path.ParentNavigationProperty); if (parentProperty.ContainmentTarget != null) { throw new InvalidOperationException( Strings.BaseServiceProvider_AccessPathTargetAlreadySpecified( path.ParentNavigationProperty, path.Parent, parentProperty.ContainmentTarget.Name, child.Name)); } if (parentProperty.Kind != ResourcePropertyKind.ResourceSetReference) { // Because it's a to-one reference doesn't actually add any syntactic sugar, we skip this case. if (path.InferredFromSchema) { continue; } else { throw new InvalidOperationException( Strings.BaseServiceProvider_AccessPathNotThroughCollection(path.ParentNavigationProperty)); } } parentProperty.SetupContainmentTarget(path.InternalChildKeyMapping, path.InternalParentKeyMapping, child); // If the path is canonical, mark the resource container. if (path.Canonical) { CanonicalAccessPathAttribute canonical = (CanonicalAccessPathAttribute)path; if (child.ContainmentCanonicalParent != null) { throw new InvalidOperationException( Strings.BaseServiceProvider_CanonicalPathTargetAlreadySpecified( path.ParentNavigationProperty, path.Parent, child.Name, child.ContainmentCanonicalProperty.Name, child.ContainmentCanonicalParent.Name)); } child.SetupCanonicalAccessPath(parent, parentProperty, canonical.TopLevelAccess); } } } #endif ////// Sets the Rights properties as specified on the given /// /// Configuration to apply. private void ApplyRights(DataServiceConfiguration configuration) { Debug.Assert(configuration != null, "configuration != null"); foreach (ResourceContainer container in this.EntitySets.Values) { container.Rights = configuration.GetResourceContainerRights(container); } foreach (ServiceOperation operation in this.metadata.ServiceOperations.Values) { operation.Rights = configuration.GetServiceOperationRights(operation); } } ///. /// Checks that every service operation has a result type with a container. private void CheckServiceOperationContainers() { foreach (ServiceOperation operation in this.metadata.ServiceOperations.Values) { if (operation.ResultKind == ServiceOperationResultKind.Nothing) { continue; } ResourceType resourceType = ((IDataServiceProvider)this).GetResourceType(operation.ResultType); if (resourceType.ResourceTypeKind != ResourceTypeKind.EntityType) { continue; } ResourceContainer container; bool containerFound = this.TryFindAnyContainerForType(operation.ResultType, out container); if (!containerFound) { throw new InvalidOperationException( Strings.BaseServiceProvider_ServiceOperationTypeHasNoContainer(operation.Name, operation.ResultType)); } } } ////// Returns the resource type for the corresponding clr type /// /// clrType whose corresponding resource type needs to be returned ///Returns the resource type private ResourceType GetType(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 nullable types Type elementType = Nullable.GetUnderlyingType(type); if (elementType != null && this.TypeCache.TryGetValue(elementType, out resourceType)) { return resourceType; } return null; } ////// Removes from metadata resource containers that are not visible to /// service consumers. /// private void RemoveHiddenResourceContainers() { ListentriesToRemove = new List (); foreach (KeyValuePair container in this.EntitySets) { if (container.Value.IsHidden) { entriesToRemove.Add(container.Key); } } RemoveKeys(this.EntitySets, entriesToRemove); } /// /// Removes from metadata service operations that are not visible to /// service consumers. /// private void RemoveHiddenServiceOperations() { ListentriesToRemove = new List (); foreach (KeyValuePair operation in this.metadata.ServiceOperations) { if (operation.Value.IsHidden) { entriesToRemove.Add(operation.Key); } } RemoveKeys(this.metadata.ServiceOperations, entriesToRemove); } /// /// Removes from metadata propertiers that are not visible to /// service consumers (those that references hidden resource /// containers). /// private void RemoveHiddenProperties() { foreach (ResourceType type in this.Types) { ResourceType typeEvaluated = type; while (typeEvaluated != null) { Listproperties = typeEvaluated.PropertiesDeclaredInThisType; Debug.Assert( properties == typeEvaluated.PropertiesDeclaredInThisType, "ResourceType.PropertiesDeclaredInThisType must by a mutable by-reference value for RemoveHiddenProperties to work correctly."); for (int i = properties.Count - 1; i >= 0; i--) { ResourceProperty property = properties[i]; ResourceContainer container = property.ResourceContainer; if (container != null && container.IsHidden) { properties.RemoveAt(i); } } typeEvaluated = typeEvaluated.BaseType; } } } /// /// Removes types that are no longer visible after applying the service /// configuration. /// private void RemoveHiddenTypes() { this.RemoveHiddenReferenceTypes(); this.RemoveHiddenComplexTypes(); } ////// Removes from metadata reference types that are not accessible /// through visible resource containers or visible service /// operations. /// private void RemoveHiddenReferenceTypes() { // Remove reference types that are not ancestors nor descendants // of any entity sets nor service operations. ListkeysToRemove = new List (); foreach (KeyValuePair entry in this.TypeCache) { ResourceType candidateType = entry.Value; if (candidateType.ResourceTypeKind != ResourceTypeKind.EntityType) { continue; } bool visible = false; foreach (ResourceContainer container in this.EntitySets.Values) { Debug.Assert(!container.IsHidden, "!container.IsHidden - all hidden container should have been removed before invoking RemoveHiddenTypes"); Type containerType = container.ElementType; if (containerType.IsAssignableFrom(candidateType.Type) || candidateType.Type.IsAssignableFrom(containerType)) { visible = true; break; } } if (!visible) { foreach (ServiceOperation operation in this.ServiceOperations) { Debug.Assert(!operation.IsHidden, "!operation.IsHidden - all hidden service operations should have been removed before invoking RemoveHiddenTypes"); Type operationType = operation.ResultType; if (operationType != null && (operationType.IsAssignableFrom(candidateType.Type) || candidateType.Type.IsAssignableFrom(operationType))) { visible = true; break; } } if (!visible) { keysToRemove.Add(entry.Key); } } } RemoveKeys(this.TypeCache, keysToRemove); } /// /// Removes from metadata reference types that are not accessible /// through visible types. /// private void RemoveHiddenComplexTypes() { // Make a graph of all available complex types starting from visible // reference types, then remove those missing. HashSetvisibleComplexTypes = new HashSet (EqualityComparer .Default); Stack pendingComplexTypes = new Stack (); foreach (ResourceType type in this.Types) { // If there is a entity or a complex type which is open, we can't detect // which complex types to hide. Hence we should just return and assume that // all complex types are getting used. #if ASTORIA_OPEN_OBJECT if (type.IsOpenType) { return; } #endif if (type.ResourceTypeKind == ResourceTypeKind.EntityType) { MarkComplexTypes(visibleComplexTypes, pendingComplexTypes, type); } } // If the complex type is returned by a service operation, it should be visible. foreach (ServiceOperation serviceOperation in this.ServiceOperations) { if (serviceOperation.ResultKind != ServiceOperationResultKind.Nothing) { ResourceType resourceType = this.TypeCache[serviceOperation.ResultType]; Debug.Assert(resourceType != null, "resourceType != null"); if (resourceType.ResourceTypeKind == ResourceTypeKind.ComplexType) { if (visibleComplexTypes.Add(resourceType)) { pendingComplexTypes.Push(resourceType); } } } } while (pendingComplexTypes.Count > 0) { ResourceType type = pendingComplexTypes.Pop(); Debug.Assert(type.ResourceTypeKind == ResourceTypeKind.ComplexType, "type.ResourceTypeKind == ResourceTypeKind.ComplexType"); MarkComplexTypes(visibleComplexTypes, pendingComplexTypes, type); } List keysToRemove = new List (); foreach (KeyValuePair entry in this.TypeCache) { if (entry.Value.ResourceTypeKind == ResourceTypeKind.ComplexType && !visibleComplexTypes.Contains(entry.Value)) { keysToRemove.Add(entry.Key); } } RemoveKeys(this.TypeCache, keysToRemove); } /// /// Looks for the first resource container 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(Type type, out ResourceContainer container) { Debug.Assert(type != null, "type != null"); foreach (ResourceContainer c in this.EntitySets.Values) { if (c.ElementType.IsAssignableFrom(type)) { container = c; return true; } } container = default(ResourceContainer); return false; } ////// Looks for a single resource container that the specified /// Type to look for. ////// could belong to. /// The single container that can hold the specified type; null otherwise. private ResourceContainer TryFindSingleContainerForType(Type type) { Debug.Assert(type != null, "type != null"); ResourceContainer result = null; foreach (ResourceContainer c in this.EntitySets.Values) { if (c.ElementType.IsAssignableFrom(type)) { if (result != null) { return null; } result = c; } } return result; } ////// Figure out all the disallowed entity types for each entity set in the system. /// private void DisallowDerivedEntityTypesWithNavProperties() { // Perform this check for entity sets whose root types takes part in inheritance foreach (ResourceContainer entitySet in this.EntitySets.Values.Where(es => es.ResourceType.HasDerivedTypes)) { foreach (ResourceType resourceType in this.Types) { // only takes leaf nodes into account - to make it slightly more performant // check for sub-class if (!resourceType.HasDerivedTypes && resourceType.Type.IsSubclassOf(entitySet.ResourceType.Type)) { // walk up the hierarchy and then down, adding types which are disallowed QueuehierarchyChain = new Queue (); ResourceType currentType = resourceType; do { hierarchyChain.Enqueue(currentType); currentType = currentType.BaseType; } while (currentType != entitySet.ResourceType); // If one of the type in the hierarchy chain has navigation property, then // all the sub-types need to be added to the entity set as disallowed types. bool hasNavigationProperties = false; while (hierarchyChain.Count != 0) { currentType = hierarchyChain.Dequeue(); if (hasNavigationProperties || currentType.HasNavigationProperties()) { entitySet.AddDisallowedDerivedType(currentType); hasNavigationProperties = true; } } } } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- // // 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; using System.Xml; #endregion Namespaces. ///Provides a reflection-based internal abstract class BaseServiceProvider : IDataServiceProvider, IDisposable, IUpdatable, IExpandProvider { ///implementation. 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; ////// Initializes a new System.Data.Services.BaseServiceProvider instance. /// /// Metadata for this provider. /// instance of the data source provider. protected BaseServiceProvider(MetadataCacheItem metadata, object dataSourceInstance) { WebUtil.CheckArgumentNull(metadata, "metadata"); WebUtil.CheckArgumentNull(dataSourceInstance, "dataSourceInstance"); this.metadata = metadata; this.instance = dataSourceInstance; } ///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; } } ///Gets a value indicating whether null propagation is required in expression trees. public abstract bool NullPropagationRequired { get; } ////// Provides a name for the context in which all resource containers are. /// public abstract string ResourceContextName { get; } ///Returns the list of entity sets. protected IDictionaryEntitySets { [DebuggerStepThrough] get { return this.metadata.EntitySets; } } /// Returns all known service operations. protected IEnumerableServiceOperations { [DebuggerStepThrough] get { return this.metadata.ServiceOperations.Values; } } /// Target type for the data provider protected Type Type { [DebuggerStepThrough] get { return this.metadata.Type; } } ///Returns the list of resource types. protected IEnumerableTypes { [DebuggerStepThrough] get { return this.metadata.TypeCache.Values; } } /// Returns true if the metadata is compatible with Edm V1 Schema otherwise false protected bool CompatibleWithV1Schema { get { return this.metadata.EdmVersion1Schema; } } ///Cache of resource properties per type. private DictionaryTypeCache { [DebuggerStepThrough] get { return this.metadata.TypeCache; } } /// Applies expansions to the specified ///. object to expand. /// A collection of ordered paths. /// /// An ///object of the same type as the given , /// with the results including the specified . /// /// This method may modify the public abstract IEnumerable ApplyExpansions(IQueryable queryable, ICollectionto indicate which expansions /// are included. /// /// The returned 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. /// expandPaths); /// /// Get the container name corresponding to the given navigation property /// The declaring type container name refers to the entity set that the declaring type belongs to /// /// name of the entity container that the declaring type belongs to /// declaring type /// resource navigation property ///name of the container that this property refers to public abstract ResourceContainer GetContainer(string declaringTypeContainerName, Type declaringResourceType, ResourceProperty resourceProperty); ///Gets the name of the container that holds this resource type. This method is called for open types only /// Resource to get container for. ////// The name of the container for the specified resource; null if it cannot /// be determined. /// public abstract ResourceContainer GetContainerForResourceType(Type resourceType); ///Gets the metadata document for this provider. /// Writer to which metadata XML should be written. public abstract void GetMetadata(XmlWriter writer); ////// Get the list of property names that form the ETag for the given resource instance /// /// name of the container to which the resource belongs t /// clr type of the resource whose etag properties need to be fetched ///list of property names that form the ETag for the given resource instance public abstract ICollectionGetETagProperties(string containerName, Type resourceClrType); #region IUpdatable Members /// /// Creates the resource of the given type and belonging to the given container /// /// container name to which the resource needs to be added /// full type name i.e. Namespace qualified type name of the resource ///object representing a resource of given type and belonging to the given container public abstract object CreateResource(string containerName, string fullTypeName); ////// Gets the resource of the given type that the query points to /// /// query pointing to a particular resource /// full type name i.e. Namespace qualified type name of the resource ///object representing a resource of given type and as referenced by the query public abstract object GetResource(IQueryable query, string fullTypeName); ////// 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); } ////// Resets the value of the given resource to its default value /// /// resource whose value needs to be reset ///same resource with its value reset public abstract object ResetResource(object resource); ////// Sets the value of the given property on the target object /// /// target object which defines the property /// name of the property whose value needs to be updated /// value of the property public abstract void SetValue(object targetResource, string propertyName, object propertyValue); ////// Gets the value of the given property on the target object /// /// target object which defines the property /// name of the property whose value needs to be updated ///the value of the property for the given target resource public abstract object GetValue(object targetResource, string propertyName); ////// Sets the value of the given reference property on the target object /// /// target object which defines the property /// name of the property whose value needs to be updated /// value of the property public abstract void SetReference(object targetResource, string propertyName, object propertyValue); ////// Adds the given value to the collection /// /// target object which defines the property /// name of the property whose value needs to be updated /// value of the property which needs to be added public abstract void AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded); ////// Removes the given value from the collection /// /// target object which defines the property /// name of the property whose value needs to be updated /// value of the property which needs to be removed public abstract void RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved); ////// Delete the given resource /// /// resource that needs to be deleted public abstract void DeleteResource(object targetResource); ////// Saves all the pending changes made till now /// public abstract void SaveChanges(); ////// Returns the actual instance of the resource represented by the given resource object /// /// object representing the resource whose instance needs to be fetched ///The actual instance of the resource represented by the given resource object public abstract object ResolveResource(object resource); ////// Revert all the pending changes. /// public abstract void ClearChanges(); #endregion #region IDataServiceProvider Members ////// Applies the settings specified in the given /// Configuration to apply. /// Instance of the data source for the provider. void IDataServiceProvider.ApplyConfiguration(DataServiceConfiguration configuration, object dataSourceInstance) { Debug.Assert(configuration != null, "configuration != null"); this.PopulateMetadataForUserSpecifiedTypes(configuration.GetKnownTypes(), this.TypeCache, this.EntitySets.Values); this.ApplyRights(configuration); this.CheckConfigurationConsistency(dataSourceInstance); this.RemoveHiddenResourceContainers(); this.RemoveHiddenServiceOperations(); this.RemoveHiddenProperties(); this.RemoveHiddenTypes(); this.CheckServiceOperationContainers(); this.DisallowDerivedEntityTypesWithNavProperties(); } ///. /// Disposes of the underlying void IDataServiceProvider.DisposeDataSource() { WebUtil.Dispose(this.instance); this.instance = null; } ///. Gets all available containers. ///An enumerable object with all available containers. IEnumerableIDataServiceProvider.GetContainers() { return this.EntitySets.Values; } /// /// Returns the IQueryable that represents the container. /// /// Name of the resource container. ////// An IQueryable that represents the container; null if there is /// no container for the specified name. /// IQueryable IDataServiceProvider.ResolveContainerName(string containerName) { ResourceContainer resourceContainer = ((IDataServiceProvider)this).TryResolveContainerName(containerName); if (resourceContainer != null) { return this.GetResourceContainerInstance(resourceContainer); } else { return null; } } ///Gets the root type of the given resource type. /// ResourceType to get least derived type for. ///The least derived type for the specified ResourceType IDataServiceProvider.GetRootType(ResourceType resourceType) { if (resourceType == null) { return resourceType; } while (resourceType.BaseType != null) { resourceType = resourceType.BaseType; } return resourceType; } ///. Gets the ///for the specified . to map into a . /// The ResourceType IDataServiceProvider.GetResourceType(Type type) { Debug.Assert(type != null, "type != null"); return this.GetType(type); } ///that maps to for this provider. Gets the kind of resource that the type is. ///to check. /// The kind of resource that the specified ResourceTypeKind IDataServiceProvider.GetResourceTypeKind(Type type) { Debug.Assert(type != null, "type != null"); ResourceType resourceType = this.GetType(type); Debug.Assert(resourceType != null, "resourceType != null -- otherwise the specified Type '" + type + "' isn't part of the known type system."); return resourceType.ResourceTypeKind; } ///is. Given the specified name, tries to find a resource container. /// Name of the resource container to resolve. ///Resolved resource container, possibly null. ResourceContainer IDataServiceProvider.TryResolveContainerName(string name) { ResourceContainer resourceContainer; if (this.EntitySets.TryGetValue(name, out resourceContainer)) { return resourceContainer; } else { return null; } } ///Given the specified CLR type, finds the named property. /// Type to get property for. /// Name of property to resolve. ///Resolved property, possibly null. ////// ResourceProperty IDataServiceProvider.TryResolvePropertyName(Type type, string propertyName) { Debug.Assert(type != null, "type != null"); Debug.Assert(propertyName != null, "propertyName != null"); // Look for a known type. ResourceType resourceType; if (this.TypeCache.TryGetValue(type, out resourceType)) { return resourceType.TryResolvePropertyName(propertyName); } // The property wasn't found. return null; } ///should be a resource type or a complex type. /// Given the specified name, tries to find a service operation. /// Name of the service operation to resolve. ///Resolved operation, possibly null. ServiceOperation IDataServiceProvider.TryResolveServiceOperation(string name) { Debug.Assert(name != null, "name != null"); ServiceOperation result; if (this.metadata.ServiceOperations.TryGetValue(name, out result)) { return result; } else { return null; } } ///Given the specified name, tries to find a type. /// Name of the type to resolve. ///Resolved resource type, possibly null. ResourceType IDataServiceProvider.TryResolveTypeName(string name) { Debug.Assert(name != null, "name != null"); 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) { return t; } } return null; } #endregion //IDataServiceProvider Members ///Releases the current data source object as necessary. void IDisposable.Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } ////// 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; } } ///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, false); } else if (methodInfo.GetCustomAttributes(typeof(WebInvokeAttribute), true).Length != 0) { this.AddServiceOperation(methodInfo, true); } } } ///Populates the metadata for the given provider. internal void PopulateMetadata() { // Add the primitive types to the type cache. foreach (ResourceType resourceType in WebUtil.GetPrimitiveTypes()) { this.TypeCache.Add(resourceType.Type, resourceType); } this.PopulateMetadata(this.TypeCache, this.EntitySets); #if ASTORIA_CONTAINMENT this.ApplyAccessPaths(); #endif } #region Protected methods. ////// Writes the edmx elements for the metadata document. /// /// xml writer into which the metadata document needs to be written. protected static void WriteTopLevelSchemaElements(XmlWriter writer) { writer.WriteStartElement(XmlConstants.EdmxNamespacePrefix, XmlConstants.EdmxElement, XmlConstants.EdmxNamespace); writer.WriteAttributeString(XmlConstants.EdmxVersion, XmlConstants.EdmxVersionValue); writer.WriteStartElement(XmlConstants.EdmxNamespacePrefix, XmlConstants.EdmxDataServicesElement, XmlConstants.EdmxNamespace); } ////// Writes the lop level schema element /// /// xml writer into which the schema node definition is written to /// namespace of the schema /// true if the metadata is compatible with the edm v1 schema protected static void WriteSchemaElement(XmlWriter writer, string schemaNamespace, bool compatibleWithV1Schema) { if (compatibleWithV1Schema) { writer.WriteStartElement(XmlConstants.Schema, XmlConstants.EdmV1Namespace); } else { writer.WriteStartElement(XmlConstants.Schema, XmlConstants.EdmV2Namespace); } writer.WriteAttributeString(XmlConstants.Namespace, schemaNamespace); writer.WriteAttributeString(XmlConstants.XmlnsNamespacePrefix, XmlConstants.DataWebNamespacePrefix, null, XmlConstants.DataWebNamespace); writer.WriteAttributeString(XmlConstants.XmlnsNamespacePrefix, XmlConstants.DataWebMetadataNamespacePrefix, null, XmlConstants.DataWebMetadataNamespace); } ////// 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); } ///Writes an attribute in the dataweb metadata namespace. /// XmlWriter in which the attribute needs to be written /// Attribute name. /// Attribute value. protected static void WriteDataWebMetadata(XmlWriter writer, string name, string value) { Debug.Assert(writer != null, "writer != null"); Debug.Assert(name != null, "name != null"); Debug.Assert(value != null, "value != null"); writer.WriteAttributeString(XmlConstants.DataWebMetadataNamespacePrefix, name, XmlConstants.DataWebMetadataNamespace, value); } ///Checks that the applied configuration is consistent. /// Instance of the data source for the provider. ///At this point in initialization, metadata trimming hasn't taken place. protected virtual void CheckConfigurationConsistency(object dataSourceInstance) { } ///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) { ((IDataServiceProvider)this).DisposeDataSource(); } #if ASTORIA_CONTAINMENT ////// Returns an object that can enumerate all ////// instances that apply to this model. /// /// An object that can enumerate all protected abstract IEnumerable/// instances that apply to this model. /// EnumerateAccessPathAttributes(); #endif /// /// Writes the service operations as FunctionImports in the specified /// Writer to which CSDL is being written to. /// Enumeration of service operations to be written. protected void WriteServiceOperations( XmlWriter writer, IEnumerable. /// serviceOperations) { Debug.Assert(writer != null, "writer != null"); foreach (ServiceOperation operation in serviceOperations) { string returnTypeString; string entitySetName = null; if (operation.ResultKind == ServiceOperationResultKind.Nothing) { returnTypeString = null; } else { ResourceType resourceType = ((IDataServiceProvider)this).GetResourceType(operation.ResultType); returnTypeString = resourceType.FullName; if (resourceType.ResourceTypeKind == ResourceTypeKind.EntityType) { ResourceContainer container = operation.EntitySet; Debug.Assert( container != null, "this.TryFindAnyContainerForType(operation.ResultType, out container) -- otherwise, we didn't trim operation '" + operation.Name + "' based on its type having no container."); entitySetName = container.Name; } if (operation.ResultKind != ServiceOperationResultKind.QueryWithSingleResult && operation.ResultKind != ServiceOperationResultKind.DirectValue) { Debug.Assert( operation.ResultKind == ServiceOperationResultKind.Enumeration || operation.ResultKind == ServiceOperationResultKind.QueryWithMultipleResults, operation.ResultKind + " == Enumeration or QueryWithMultipleResults"); returnTypeString = String.Format(CultureInfo.InvariantCulture, XmlConstants.EdmCollectionTypeFormat, returnTypeString); } } writer.WriteStartElement(XmlConstants.EdmFunctionImportElementName); writer.WriteAttributeString(XmlConstants.Name, operation.Name); if (entitySetName != null) { writer.WriteAttributeString(XmlConstants.EdmEntitySetAttributeName, entitySetName); } if (returnTypeString != null) { writer.WriteAttributeString(XmlConstants.EdmReturnTypeAttributeName, returnTypeString); } string verb = operation.Invoke ? XmlConstants.HttpMethodPost : XmlConstants.HttpMethodGet; BaseServiceProvider.WriteDataWebMetadata(writer, XmlConstants.ServiceOperationHttpMethodName, verb); if (!String.IsNullOrEmpty(operation.MimeType)) { BaseServiceProvider.WriteDataWebMetadata(writer, XmlConstants.DataWebMimeTypeAttributeName, operation.MimeType); } foreach (ServiceOperationParameter parameter in operation.Parameters) { writer.WriteStartElement(XmlConstants.EdmParameterElementName); writer.WriteAttributeString(XmlConstants.Name, parameter.Name); writer.WriteAttributeString(XmlConstants.Type, WebUtil.GetEdmTypeName(parameter.Type)); writer.WriteAttributeString(XmlConstants.EdmModeAttributeName, XmlConstants.EdmModeInValue); writer.WriteEndElement(); } writer.WriteEndElement(); } } /// /// Creates the object query for the given resource container and returns it /// /// resource container for which IQueryable instance needs to be created ///returns the IQueryable instance for the given resource container protected abstract IQueryable GetResourceContainerInstance(ResourceContainer resourceContainer); ////// Populates the metadata for the given provider /// /// list of known types /// list of entity sets protected abstract void PopulateMetadata( IDictionaryknownTypes, IDictionary entitySets); /// /// Populate types for metadata specified by the provider /// /// list of types specified by the provider /// list of already known types /// list of entity sets as specified in the data source type protected abstract void PopulateMetadataForUserSpecifiedTypes(IEnumerableuserSpecifiedTypes, IDictionary knownTypes, IEnumerable entitySets); /// /// Populate metadata for the given clr type. /// /// type whose metadata needs to be loaded. /// list of already known resource types. /// 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, IEnumerable entitySets); #endregion Protected 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<>); } ////// Removes the entries from ///in the /// specified . /// Type of dictionary key to remove. ///Type of dictionary value to remove. /// Dictionary from which entries should be removed. /// Keys for entries to remove from. private static void RemoveKeys (IDictionary dictionary, IEnumerable keys) { Debug.Assert(dictionary != null, "dictionary != null"); Debug.Assert(keys != null, "keys != null"); foreach (TKey key in keys) { bool removed = dictionary.Remove(key); Debug.Assert(removed, "removed - key " + key.ToString() + " should be present."); } } /// /// Marks complex types from the specified /// Set of types that have been marked. /// Types that need to be examined further. /// Type with properties to mark. private static void MarkComplexTypes(HashSet/// by adding them to the given , /// and adding them to the /// to be examined later if this is the first time they are seen. /// markedTypes, Stack pendingTypes, ResourceType type) { foreach (ResourceProperty property in type.Properties) { if (property.TypeKind == ResourceTypeKind.ComplexType) { Debug.Assert(property.ResourceType != null, "property.ResourceType != null"); Debug.Assert(property.ResourceType.ResourceTypeKind == ResourceTypeKind.ComplexType, "property.ResourceType.ResourceTypeKind == ResourceTypeKind.ComplexType"); bool added = markedTypes.Add(property.ResourceType); if (added) { pendingTypes.Push(property.ResourceType); } } } } /// /// Adds a new /// Method to expose as a service operation. /// Whether invocation is required. private void AddServiceOperation(MethodInfo method, bool invoke) { Debug.Assert(method != null, "method != null"); Debug.Assert(!method.IsAbstract, "!method.IsAbstract - if method is abstract, the type is abstract - already checked"); if (this.metadata.ServiceOperations.ContainsKey(method.Name)) { throw new InvalidOperationException(Strings.BaseServiceProvider_OverloadingNotSupported(this.Type, method)); } bool hasSingleResult = SingleResultAttribute.MethodHasSingleResult(method); ServiceOperationResultKind resultKind; Type resultType; ResourceType resourceType; if (method.ReturnType == typeof(void)) { resultKind = ServiceOperationResultKind.Nothing; resultType = typeof(void); resourceType = null; this.metadata.EdmVersion1Schema = false; } else { resourceType = this.GetType(method.ReturnType); if (resourceType != null) { resultKind = ServiceOperationResultKind.DirectValue; resultType = method.ReturnType; this.metadata.EdmVersion1Schema = false; } 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) { if (hasSingleResult) { throw new InvalidOperationException(Strings.BaseServiceProvider_IEnumerableAlwaysMultiple(this.Type, method)); } resultKind = ServiceOperationResultKind.Enumeration; resultType = enumerableElement; } else { resultType = method.ReturnType; resultKind = ServiceOperationResultKind.DirectValue; this.metadata.EdmVersion1Schema = false; } } resourceType = this.PopulateMetadataForType(resultType, this.TypeCache, this.EntitySets.Values); if (resourceType == null) { throw new InvalidOperationException(Strings.BaseServiceProvider_UnsupportedReturnType(method, method.ReturnType)); } if (hasSingleResult || (!hasSingleResult && (resourceType.ResourceTypeKind == ResourceTypeKind.ComplexType || resourceType.ResourceTypeKind == ResourceTypeKind.Primitive))) { this.metadata.EdmVersion1Schema = false; } } } string mimeType = MimeTypeAttribute.GetMemberMimeType(method); ParameterInfo[] parametersInfo = method.GetParameters(); ServiceOperationParameter[] parameters = new ServiceOperationParameter[parametersInfo.Length]; for (int i = 0; i < parameters.Length; i++) { if (parametersInfo[i].IsOut || parametersInfo[i].IsRetval) { throw new InvalidOperationException(Strings.BaseServiceProvider_ParameterNotIn(method, parametersInfo[i])); } if (!WebUtil.IsPrimitiveType(parametersInfo[i].ParameterType)) { throw new InvalidOperationException( Strings.BaseServiceProvider_ParameterTypeNotSupported(method, parametersInfo[i], parametersInfo[i].ParameterType)); } string parameterName = parametersInfo[i].Name ?? "p" + i.ToString(CultureInfo.InvariantCulture); parameters[i] = new ServiceOperationParameter(parameterName, parametersInfo[i].ParameterType); } ServiceOperation operation = new ServiceOperation(method, resultKind, resultType, mimeType, invoke, parameters); this.metadata.ServiceOperations.Add(method.Name, operation); if (resourceType != null && resourceType.ResourceTypeKind == ResourceTypeKind.EntityType) { operation.EntitySet = this.TryFindSingleContainerForType(resultType); if (operation.EntitySet == null) { throw new InvalidOperationException( Strings.BaseServiceProvider_ServiceOperationMissingSingleEntitySet(method, resourceType.FullName)); } } } #if ASTORIA_CONTAINMENT ///based on the specified /// instance. /// Applies access path attributes to the model. private void ApplyAccessPaths() { foreach (AccessPathAttribute path in this.EnumerateAccessPathAttributes()) { Debug.Assert(path != null, "path != null -- otherwise EnumerateAccessPathAttributes is incorrect."); Debug.Assert( path.AnnotatedContainer != null, "path.AnnotatedContainer -- otherwise EnumerateAccessPathAttributes is incorrect."); // When an access path is inferred from schema, full validation hasn't taken place. Validation // errors for inferred values from here on should be ignored, with the result that the proposed // access path doesn't take effect. Exception exception = path.Validate(this); if (exception != null) { if (path.InferredFromSchema) { continue; } else { throw exception; } } // Mark the NavigationProperty with the appropriate values. IDataServiceProvider provider = (IDataServiceProvider)this; ResourceContainer child = path.AnnotatedContainer; ResourceContainer parent = provider.TryResolveContainerName(path.Parent); ResourceProperty parentProperty = parent.ResourceType.TryResolvePropertyName(path.ParentNavigationProperty); if (parentProperty.ContainmentTarget != null) { throw new InvalidOperationException( Strings.BaseServiceProvider_AccessPathTargetAlreadySpecified( path.ParentNavigationProperty, path.Parent, parentProperty.ContainmentTarget.Name, child.Name)); } if (parentProperty.Kind != ResourcePropertyKind.ResourceSetReference) { // Because it's a to-one reference doesn't actually add any syntactic sugar, we skip this case. if (path.InferredFromSchema) { continue; } else { throw new InvalidOperationException( Strings.BaseServiceProvider_AccessPathNotThroughCollection(path.ParentNavigationProperty)); } } parentProperty.SetupContainmentTarget(path.InternalChildKeyMapping, path.InternalParentKeyMapping, child); // If the path is canonical, mark the resource container. if (path.Canonical) { CanonicalAccessPathAttribute canonical = (CanonicalAccessPathAttribute)path; if (child.ContainmentCanonicalParent != null) { throw new InvalidOperationException( Strings.BaseServiceProvider_CanonicalPathTargetAlreadySpecified( path.ParentNavigationProperty, path.Parent, child.Name, child.ContainmentCanonicalProperty.Name, child.ContainmentCanonicalParent.Name)); } child.SetupCanonicalAccessPath(parent, parentProperty, canonical.TopLevelAccess); } } } #endif ////// Sets the Rights properties as specified on the given /// /// Configuration to apply. private void ApplyRights(DataServiceConfiguration configuration) { Debug.Assert(configuration != null, "configuration != null"); foreach (ResourceContainer container in this.EntitySets.Values) { container.Rights = configuration.GetResourceContainerRights(container); } foreach (ServiceOperation operation in this.metadata.ServiceOperations.Values) { operation.Rights = configuration.GetServiceOperationRights(operation); } } ///. /// Checks that every service operation has a result type with a container. private void CheckServiceOperationContainers() { foreach (ServiceOperation operation in this.metadata.ServiceOperations.Values) { if (operation.ResultKind == ServiceOperationResultKind.Nothing) { continue; } ResourceType resourceType = ((IDataServiceProvider)this).GetResourceType(operation.ResultType); if (resourceType.ResourceTypeKind != ResourceTypeKind.EntityType) { continue; } ResourceContainer container; bool containerFound = this.TryFindAnyContainerForType(operation.ResultType, out container); if (!containerFound) { throw new InvalidOperationException( Strings.BaseServiceProvider_ServiceOperationTypeHasNoContainer(operation.Name, operation.ResultType)); } } } ////// Returns the resource type for the corresponding clr type /// /// clrType whose corresponding resource type needs to be returned ///Returns the resource type private ResourceType GetType(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 nullable types Type elementType = Nullable.GetUnderlyingType(type); if (elementType != null && this.TypeCache.TryGetValue(elementType, out resourceType)) { return resourceType; } return null; } ////// Removes from metadata resource containers that are not visible to /// service consumers. /// private void RemoveHiddenResourceContainers() { ListentriesToRemove = new List (); foreach (KeyValuePair container in this.EntitySets) { if (container.Value.IsHidden) { entriesToRemove.Add(container.Key); } } RemoveKeys(this.EntitySets, entriesToRemove); } /// /// Removes from metadata service operations that are not visible to /// service consumers. /// private void RemoveHiddenServiceOperations() { ListentriesToRemove = new List (); foreach (KeyValuePair operation in this.metadata.ServiceOperations) { if (operation.Value.IsHidden) { entriesToRemove.Add(operation.Key); } } RemoveKeys(this.metadata.ServiceOperations, entriesToRemove); } /// /// Removes from metadata propertiers that are not visible to /// service consumers (those that references hidden resource /// containers). /// private void RemoveHiddenProperties() { foreach (ResourceType type in this.Types) { ResourceType typeEvaluated = type; while (typeEvaluated != null) { Listproperties = typeEvaluated.PropertiesDeclaredInThisType; Debug.Assert( properties == typeEvaluated.PropertiesDeclaredInThisType, "ResourceType.PropertiesDeclaredInThisType must by a mutable by-reference value for RemoveHiddenProperties to work correctly."); for (int i = properties.Count - 1; i >= 0; i--) { ResourceProperty property = properties[i]; ResourceContainer container = property.ResourceContainer; if (container != null && container.IsHidden) { properties.RemoveAt(i); } } typeEvaluated = typeEvaluated.BaseType; } } } /// /// Removes types that are no longer visible after applying the service /// configuration. /// private void RemoveHiddenTypes() { this.RemoveHiddenReferenceTypes(); this.RemoveHiddenComplexTypes(); } ////// Removes from metadata reference types that are not accessible /// through visible resource containers or visible service /// operations. /// private void RemoveHiddenReferenceTypes() { // Remove reference types that are not ancestors nor descendants // of any entity sets nor service operations. ListkeysToRemove = new List (); foreach (KeyValuePair entry in this.TypeCache) { ResourceType candidateType = entry.Value; if (candidateType.ResourceTypeKind != ResourceTypeKind.EntityType) { continue; } bool visible = false; foreach (ResourceContainer container in this.EntitySets.Values) { Debug.Assert(!container.IsHidden, "!container.IsHidden - all hidden container should have been removed before invoking RemoveHiddenTypes"); Type containerType = container.ElementType; if (containerType.IsAssignableFrom(candidateType.Type) || candidateType.Type.IsAssignableFrom(containerType)) { visible = true; break; } } if (!visible) { foreach (ServiceOperation operation in this.ServiceOperations) { Debug.Assert(!operation.IsHidden, "!operation.IsHidden - all hidden service operations should have been removed before invoking RemoveHiddenTypes"); Type operationType = operation.ResultType; if (operationType != null && (operationType.IsAssignableFrom(candidateType.Type) || candidateType.Type.IsAssignableFrom(operationType))) { visible = true; break; } } if (!visible) { keysToRemove.Add(entry.Key); } } } RemoveKeys(this.TypeCache, keysToRemove); } /// /// Removes from metadata reference types that are not accessible /// through visible types. /// private void RemoveHiddenComplexTypes() { // Make a graph of all available complex types starting from visible // reference types, then remove those missing. HashSetvisibleComplexTypes = new HashSet (EqualityComparer .Default); Stack pendingComplexTypes = new Stack (); foreach (ResourceType type in this.Types) { // If there is a entity or a complex type which is open, we can't detect // which complex types to hide. Hence we should just return and assume that // all complex types are getting used. #if ASTORIA_OPEN_OBJECT if (type.IsOpenType) { return; } #endif if (type.ResourceTypeKind == ResourceTypeKind.EntityType) { MarkComplexTypes(visibleComplexTypes, pendingComplexTypes, type); } } // If the complex type is returned by a service operation, it should be visible. foreach (ServiceOperation serviceOperation in this.ServiceOperations) { if (serviceOperation.ResultKind != ServiceOperationResultKind.Nothing) { ResourceType resourceType = this.TypeCache[serviceOperation.ResultType]; Debug.Assert(resourceType != null, "resourceType != null"); if (resourceType.ResourceTypeKind == ResourceTypeKind.ComplexType) { if (visibleComplexTypes.Add(resourceType)) { pendingComplexTypes.Push(resourceType); } } } } while (pendingComplexTypes.Count > 0) { ResourceType type = pendingComplexTypes.Pop(); Debug.Assert(type.ResourceTypeKind == ResourceTypeKind.ComplexType, "type.ResourceTypeKind == ResourceTypeKind.ComplexType"); MarkComplexTypes(visibleComplexTypes, pendingComplexTypes, type); } List keysToRemove = new List (); foreach (KeyValuePair entry in this.TypeCache) { if (entry.Value.ResourceTypeKind == ResourceTypeKind.ComplexType && !visibleComplexTypes.Contains(entry.Value)) { keysToRemove.Add(entry.Key); } } RemoveKeys(this.TypeCache, keysToRemove); } /// /// Looks for the first resource container 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(Type type, out ResourceContainer container) { Debug.Assert(type != null, "type != null"); foreach (ResourceContainer c in this.EntitySets.Values) { if (c.ElementType.IsAssignableFrom(type)) { container = c; return true; } } container = default(ResourceContainer); return false; } ////// Looks for a single resource container that the specified /// Type to look for. ////// could belong to. /// The single container that can hold the specified type; null otherwise. private ResourceContainer TryFindSingleContainerForType(Type type) { Debug.Assert(type != null, "type != null"); ResourceContainer result = null; foreach (ResourceContainer c in this.EntitySets.Values) { if (c.ElementType.IsAssignableFrom(type)) { if (result != null) { return null; } result = c; } } return result; } ////// Figure out all the disallowed entity types for each entity set in the system. /// private void DisallowDerivedEntityTypesWithNavProperties() { // Perform this check for entity sets whose root types takes part in inheritance foreach (ResourceContainer entitySet in this.EntitySets.Values.Where(es => es.ResourceType.HasDerivedTypes)) { foreach (ResourceType resourceType in this.Types) { // only takes leaf nodes into account - to make it slightly more performant // check for sub-class if (!resourceType.HasDerivedTypes && resourceType.Type.IsSubclassOf(entitySet.ResourceType.Type)) { // walk up the hierarchy and then down, adding types which are disallowed QueuehierarchyChain = new Queue (); ResourceType currentType = resourceType; do { hierarchyChain.Enqueue(currentType); currentType = currentType.BaseType; } while (currentType != entitySet.ResourceType); // If one of the type in the hierarchy chain has navigation property, then // all the sub-types need to be added to the entity set as disallowed types. bool hasNavigationProperties = false; while (hierarchyChain.Count != 0) { currentType = hierarchyChain.Dequeue(); if (hasNavigationProperties || currentType.HasNavigationProperties()) { entitySet.AddDisallowedDerivedType(currentType); hasNavigationProperties = true; } } } } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- MobileUserControlDesigner.cs
- Queue.cs
- SqlUserDefinedTypeAttribute.cs
- MemoryPressure.cs
- UserNamePasswordValidator.cs
- IImplicitResourceProvider.cs
- IDispatchConstantAttribute.cs
- SafeHandle.cs
- SafeLibraryHandle.cs
- Storyboard.cs
- MethodCallTranslator.cs
- XmlDesignerDataSourceView.cs
- ContentFilePart.cs
- RuntimeResourceSet.cs
- CreatingCookieEventArgs.cs
- SchemaLookupTable.cs
- GeometryDrawing.cs
- BehaviorService.cs
- DocumentOrderQuery.cs
- IsolationInterop.cs
- ResponseBodyWriter.cs
- ValueTypeIndexerReference.cs
- ObjectAssociationEndMapping.cs
- ToolZone.cs
- Application.cs
- FontNameConverter.cs
- ConnectionManagementElementCollection.cs
- Panel.cs
- TypeUsage.cs
- PageVisual.cs
- X509CertificateCollection.cs
- DataTableClearEvent.cs
- ExpressionEditor.cs
- NameGenerator.cs
- HostedBindingBehavior.cs
- DateTimeConverter2.cs
- AvTrace.cs
- XomlCompilerHelpers.cs
- UIPermission.cs
- CodeGenerator.cs
- ListSourceHelper.cs
- TextLine.cs
- MetaTableHelper.cs
- odbcmetadatacollectionnames.cs
- CheckBoxPopupAdapter.cs
- ContactManager.cs
- CodeSpit.cs
- EnglishPluralizationService.cs
- ApplyTemplatesAction.cs
- StreamingContext.cs
- XamlSerializerUtil.cs
- DisposableCollectionWrapper.cs
- PointCollectionConverter.cs
- MenuEventArgs.cs
- WmlCalendarAdapter.cs
- CapiNative.cs
- DayRenderEvent.cs
- StateItem.cs
- Figure.cs
- ChildChangedEventArgs.cs
- UserControlCodeDomTreeGenerator.cs
- ApplicationDirectory.cs
- FixUp.cs
- CombinedTcpChannel.cs
- XmlSchemaImporter.cs
- IISUnsafeMethods.cs
- SignedXml.cs
- DocumentApplicationState.cs
- FontSourceCollection.cs
- ItemsPanelTemplate.cs
- AuthorizationRule.cs
- Color.cs
- FaultContractInfo.cs
- MediaTimeline.cs
- ByteRangeDownloader.cs
- XmlText.cs
- JsonReader.cs
- RangeBase.cs
- NamespaceDisplayAutomationPeer.cs
- CodeTypeOfExpression.cs
- WebPartMenu.cs
- CollectionViewSource.cs
- FramingEncoders.cs
- DataGridClipboardCellContent.cs
- BindingRestrictions.cs
- Msec.cs
- Solver.cs
- CounterCreationDataCollection.cs
- WebPartManagerInternals.cs
- BufferedReadStream.cs
- SecurityContextSecurityTokenParameters.cs
- MessageSecurityProtocolFactory.cs
- TextDecorationLocationValidation.cs
- AttachedPropertyBrowsableWhenAttributePresentAttribute.cs
- PageTheme.cs
- SmtpCommands.cs
- ImageFormatConverter.cs
- DesignerSerializationVisibilityAttribute.cs
- ListViewTableCell.cs
- MatrixAnimationUsingPath.cs