Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Client / System / Data / Services / Client / Binding / BindingEntityInfo.cs / 1305376 / BindingEntityInfo.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // //// BindingEntityInfo class // // //--------------------------------------------------------------------- namespace System.Data.Services.Client { #region Namespaces using System.Collections.Generic; using System.ComponentModel; using System.Data.Services.Common; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Threading; #endregion ///Type of property stored in BindingPropertyInfo. internal enum BindingPropertyKind { ///Property type is a complex type. BindingPropertyKindComplex, ///Property type is an entity type with keys. BindingPropertyKindEntity, ///Property is of an DataServiceCollection. BindingPropertyKindCollection } ///Cache of information about entity types and their observable properties internal class BindingEntityInfo { ///Object reference used as a 'False' flag. private static readonly object FalseObject = new object(); ///Object reference used as a 'False' flag. private static readonly object TrueObject = new object(); ///Lock on metadata caches. private static readonly ReaderWriterLockSlim metadataCacheLock = new ReaderWriterLockSlim(); ///Types which are known not to be entity types. private static readonly HashSetknownNonEntityTypes = new HashSet (EqualityComparer .Default); /// Types which are known to be (or not) collection types. private static readonly DictionaryknownObservableCollectionTypes = new Dictionary (EqualityComparer .Default); /// Mapping between types and their corresponding entity information private static readonly DictionarybindingEntityInfos = new Dictionary (EqualityComparer .Default); /// Obtain binding info corresponding to a given type /// Type for which to obtain information ///Info about the internal static IListGetObservableProperties(Type entityType) { return GetBindingEntityInfoFor(entityType).ObservableProperties; } /// Gets the ClientType corresponding to the given type /// Input type ///Corresponding ClientType internal static ClientType GetClientType(Type entityType) { return GetBindingEntityInfoFor(entityType).ClientType; } ////// Get the entity set name for the target entity object. /// /// An entity object. /// The 'currently known' entity set name for the target object. ///The entity set name for the target object. ////// Allow user code to provide the entity set name. If user code does not provide the entity set name, then /// this method will get the entity set name from the value of the EntitySetAttribute. /// The 'currently known' entity set name for top level collections can be provided through OEC constructor /// internal static string GetEntitySet( object target, string targetEntitySet) { Debug.Assert(target != null, "Argument 'target' cannot be null."); Debug.Assert(BindingEntityInfo.IsEntityType(target.GetType()), "Argument 'target' must be an entity type."); // Here's the rules in order of priority for resolving entity set name // 1. EntitySet name passed in the constructor or extension methods of DataServiceCollection // 2. EntitySet name specified in the EntitySet attribute by the code gen. {Remember this attribute is // not generated in case of MEST) if (!String.IsNullOrEmpty(targetEntitySet)) { return targetEntitySet; } else { // If there is not a 'currently known' entity set name to validate against, then there must be // EntitySet attribute on the entity type return BindingEntityInfo.GetEntitySetAttribute(target.GetType()); } } ////// Determine if the specified type is an DataServiceCollection. /// ////// If there a generic class in the inheritance hierarchy of the type, that has a single /// entity type paramenter T, and is assignable to DataServiceCollection(Of T), then /// the type is an DataServiceCollection. /// /// An object type specifier. ///True if the type is an DataServiceCollection; otherwise false. internal static bool IsDataServiceCollection(Type collectionType) { Debug.Assert(collectionType != null, "Argument 'collectionType' cannot be null."); metadataCacheLock.EnterReadLock(); try { object resultAsObject; if (knownObservableCollectionTypes.TryGetValue(collectionType, out resultAsObject)) { return resultAsObject == TrueObject; } } finally { metadataCacheLock.ExitReadLock(); } Type type = collectionType; bool result = false; while (type != null) { if (type.IsGenericType) { // Is there a generic class in the inheritance hierarchy, that has a single // entity type paramenter T, and is assignable to DataServiceCollectionType[] parms = type.GetGenericArguments(); if (parms != null && parms.Length == 1 && IsEntityType(parms[0])) { // if ObservableCollection is not available dataServiceCollection will be null Type dataServiceCollection = WebUtil.GetDataServiceCollectionOfT(parms); if (dataServiceCollection != null && dataServiceCollection.IsAssignableFrom(type)) { result = true; break; } } } type = type.BaseType; } metadataCacheLock.EnterWriteLock(); try { if (!knownObservableCollectionTypes.ContainsKey(collectionType)) { knownObservableCollectionTypes[collectionType] = result ? TrueObject : FalseObject; } } finally { metadataCacheLock.ExitWriteLock(); } return result; } /// /// Determine if the specified type is an entity type. /// /// An object type specifier. ///True if the type is an entity type; otherwise false. internal static bool IsEntityType(Type type) { Debug.Assert(type != null, "Argument 'type' cannot be null."); metadataCacheLock.EnterReadLock(); try { if (knownNonEntityTypes.Contains(type)) { return false; } } finally { metadataCacheLock.ExitReadLock(); } try { if (BindingEntityInfo.IsDataServiceCollection(type)) { return false; } return ClientType.Create(type).IsEntityType; } catch (InvalidOperationException) { metadataCacheLock.EnterWriteLock(); try { if (!knownNonEntityTypes.Contains(type)) { knownNonEntityTypes.Add(type); } } finally { metadataCacheLock.ExitWriteLock(); } return false; } } ////// Gets the value of a property and corresponding BindingPropertyInfo if property is being observed /// /// Source object whose property needs to be read /// Name of the source object property /// BindingPropertyInfo corresponding to/// Value of the property internal static object GetPropertyValue(object source, string sourceProperty, out BindingPropertyInfo bindingPropertyInfo) { Type sourceType = source.GetType(); bindingPropertyInfo = BindingEntityInfo.GetObservableProperties(sourceType) .SingleOrDefault(x => x.PropertyInfo.PropertyName == sourceProperty); // bindingPropertyInfo is null for primitive properties. if (bindingPropertyInfo == null) { return BindingEntityInfo.GetClientType(sourceType) .GetProperty(sourceProperty, false) .GetValue(source); } else { return bindingPropertyInfo.PropertyInfo.GetValue(source); } } ///Obtain binding info corresponding to a given type /// Type for which to obtain information ///Info about the private static BindingEntityInfoPerType GetBindingEntityInfoFor(Type entityType) { BindingEntityInfoPerType bindingEntityInfo; metadataCacheLock.EnterReadLock(); try { if (bindingEntityInfos.TryGetValue(entityType, out bindingEntityInfo)) { return bindingEntityInfo; } } finally { metadataCacheLock.ExitReadLock(); } bindingEntityInfo = new BindingEntityInfoPerType(); // Try to get the entity set name from the EntitySetAttribute attributes. In order to make the // inheritance work, we need to look at the attributes declared in the base types also. object[] attributes = entityType.GetCustomAttributes(typeof(EntitySetAttribute), true); // There must be exactly one (unambiguous) EntitySetAttribute attribute. bindingEntityInfo.EntitySet = (attributes != null && attributes.Length == 1) ? ((EntitySetAttribute)attributes[0]).EntitySet : null; bindingEntityInfo.ClientType = ClientType.Create(entityType); foreach (ClientType.ClientProperty p in bindingEntityInfo.ClientType.Properties) { BindingPropertyInfo bpi = null; Type propertyType = p.PropertyType; if (p.CollectionType != null) { if (BindingEntityInfo.IsDataServiceCollection(propertyType)) { bpi = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindCollection }; } } else if (BindingEntityInfo.IsEntityType(propertyType)) { bpi = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindEntity }; } else if (BindingEntityInfo.CanBeComplexProperty(p)) { // Add complex types and nothing else. bpi = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindComplex }; } if (bpi != null) { bpi.PropertyInfo = p; // For complex types only treat complex typed properties as observable, we are not going to observer entity typed or primitive properties. if (bindingEntityInfo.ClientType.IsEntityType || bpi.PropertyKind == BindingPropertyKind.BindingPropertyKindComplex) { bindingEntityInfo.ObservableProperties.Add(bpi); } } } metadataCacheLock.EnterWriteLock(); try { if (!bindingEntityInfos.ContainsKey(entityType)) { bindingEntityInfos[entityType] = bindingEntityInfo; } } finally { metadataCacheLock.ExitWriteLock(); } return bindingEntityInfo; } ///Checks whether a given property can be a complex property i.e. implements INotifyPropertyChanged. /// Input property. ///true if the property is complex property, false otherwise. private static bool CanBeComplexProperty(ClientType.ClientProperty property) { Debug.Assert(property != null, "property != null"); if (typeof(INotifyPropertyChanged).IsAssignableFrom(property.PropertyType)) { Debug.Assert(!property.IsKnownType, "Known types do not implement INotifyPropertyChanged."); return true; } return false; } ///Gets entity set corresponding to a given type /// Intput type ///Entity set name for the type private static string GetEntitySetAttribute(Type entityType) { return GetBindingEntityInfoFor(entityType).EntitySet; } ///Information about a property interesting for binding internal class BindingPropertyInfo { ///Property information public ClientType.ClientProperty PropertyInfo { get; set; } ///Kind of the property i.e. complex, entity or collection. public BindingPropertyKind PropertyKind { get; set; } } ///Holder of information about entity properties for a type private sealed class BindingEntityInfoPerType { ///Collection of properties interesting to the observer private ListobservableProperties; /// Constructor public BindingEntityInfoPerType() { this.observableProperties = new List(); } /// Entity set of the entity public String EntitySet { get; set; } ///Corresponding ClientTyp public ClientType ClientType { get; set; } ///Collection of properties interesting to the observer public ListObservableProperties { get { return this.observableProperties; } } } #if ASTORIA_LIGHT /// Read-writer lock, implemented over a Monitor. private sealed class ReaderWriterLockSlim { ///Single object on which to lock. private object _lock = new object(); ///Enters a reader lock. Writers will also be blocked. internal void EnterReadLock() { Monitor.Enter(_lock); } ///Enters a writer lock. Readers will also be blocked. internal void EnterWriteLock() { Monitor.Enter(_lock); } ///Exits a reader lock. internal void ExitReadLock() { Monitor.Exit(_lock); } ///Exits a writer lock. internal void ExitWriteLock() { Monitor.Exit(_lock); } } #endif } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // //// BindingEntityInfo class // // //--------------------------------------------------------------------- namespace System.Data.Services.Client { #region Namespaces using System.Collections.Generic; using System.ComponentModel; using System.Data.Services.Common; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Threading; #endregion ///Type of property stored in BindingPropertyInfo. internal enum BindingPropertyKind { ///Property type is a complex type. BindingPropertyKindComplex, ///Property type is an entity type with keys. BindingPropertyKindEntity, ///Property is of an DataServiceCollection. BindingPropertyKindCollection } ///Cache of information about entity types and their observable properties internal class BindingEntityInfo { ///Object reference used as a 'False' flag. private static readonly object FalseObject = new object(); ///Object reference used as a 'False' flag. private static readonly object TrueObject = new object(); ///Lock on metadata caches. private static readonly ReaderWriterLockSlim metadataCacheLock = new ReaderWriterLockSlim(); ///Types which are known not to be entity types. private static readonly HashSetknownNonEntityTypes = new HashSet (EqualityComparer .Default); /// Types which are known to be (or not) collection types. private static readonly DictionaryknownObservableCollectionTypes = new Dictionary (EqualityComparer .Default); /// Mapping between types and their corresponding entity information private static readonly DictionarybindingEntityInfos = new Dictionary (EqualityComparer .Default); /// Obtain binding info corresponding to a given type /// Type for which to obtain information ///Info about the internal static IListGetObservableProperties(Type entityType) { return GetBindingEntityInfoFor(entityType).ObservableProperties; } /// Gets the ClientType corresponding to the given type /// Input type ///Corresponding ClientType internal static ClientType GetClientType(Type entityType) { return GetBindingEntityInfoFor(entityType).ClientType; } ////// Get the entity set name for the target entity object. /// /// An entity object. /// The 'currently known' entity set name for the target object. ///The entity set name for the target object. ////// Allow user code to provide the entity set name. If user code does not provide the entity set name, then /// this method will get the entity set name from the value of the EntitySetAttribute. /// The 'currently known' entity set name for top level collections can be provided through OEC constructor /// internal static string GetEntitySet( object target, string targetEntitySet) { Debug.Assert(target != null, "Argument 'target' cannot be null."); Debug.Assert(BindingEntityInfo.IsEntityType(target.GetType()), "Argument 'target' must be an entity type."); // Here's the rules in order of priority for resolving entity set name // 1. EntitySet name passed in the constructor or extension methods of DataServiceCollection // 2. EntitySet name specified in the EntitySet attribute by the code gen. {Remember this attribute is // not generated in case of MEST) if (!String.IsNullOrEmpty(targetEntitySet)) { return targetEntitySet; } else { // If there is not a 'currently known' entity set name to validate against, then there must be // EntitySet attribute on the entity type return BindingEntityInfo.GetEntitySetAttribute(target.GetType()); } } ////// Determine if the specified type is an DataServiceCollection. /// ////// If there a generic class in the inheritance hierarchy of the type, that has a single /// entity type paramenter T, and is assignable to DataServiceCollection(Of T), then /// the type is an DataServiceCollection. /// /// An object type specifier. ///True if the type is an DataServiceCollection; otherwise false. internal static bool IsDataServiceCollection(Type collectionType) { Debug.Assert(collectionType != null, "Argument 'collectionType' cannot be null."); metadataCacheLock.EnterReadLock(); try { object resultAsObject; if (knownObservableCollectionTypes.TryGetValue(collectionType, out resultAsObject)) { return resultAsObject == TrueObject; } } finally { metadataCacheLock.ExitReadLock(); } Type type = collectionType; bool result = false; while (type != null) { if (type.IsGenericType) { // Is there a generic class in the inheritance hierarchy, that has a single // entity type paramenter T, and is assignable to DataServiceCollectionType[] parms = type.GetGenericArguments(); if (parms != null && parms.Length == 1 && IsEntityType(parms[0])) { // if ObservableCollection is not available dataServiceCollection will be null Type dataServiceCollection = WebUtil.GetDataServiceCollectionOfT(parms); if (dataServiceCollection != null && dataServiceCollection.IsAssignableFrom(type)) { result = true; break; } } } type = type.BaseType; } metadataCacheLock.EnterWriteLock(); try { if (!knownObservableCollectionTypes.ContainsKey(collectionType)) { knownObservableCollectionTypes[collectionType] = result ? TrueObject : FalseObject; } } finally { metadataCacheLock.ExitWriteLock(); } return result; } /// /// Determine if the specified type is an entity type. /// /// An object type specifier. ///True if the type is an entity type; otherwise false. internal static bool IsEntityType(Type type) { Debug.Assert(type != null, "Argument 'type' cannot be null."); metadataCacheLock.EnterReadLock(); try { if (knownNonEntityTypes.Contains(type)) { return false; } } finally { metadataCacheLock.ExitReadLock(); } try { if (BindingEntityInfo.IsDataServiceCollection(type)) { return false; } return ClientType.Create(type).IsEntityType; } catch (InvalidOperationException) { metadataCacheLock.EnterWriteLock(); try { if (!knownNonEntityTypes.Contains(type)) { knownNonEntityTypes.Add(type); } } finally { metadataCacheLock.ExitWriteLock(); } return false; } } ////// Gets the value of a property and corresponding BindingPropertyInfo if property is being observed /// /// Source object whose property needs to be read /// Name of the source object property /// BindingPropertyInfo corresponding to/// Value of the property internal static object GetPropertyValue(object source, string sourceProperty, out BindingPropertyInfo bindingPropertyInfo) { Type sourceType = source.GetType(); bindingPropertyInfo = BindingEntityInfo.GetObservableProperties(sourceType) .SingleOrDefault(x => x.PropertyInfo.PropertyName == sourceProperty); // bindingPropertyInfo is null for primitive properties. if (bindingPropertyInfo == null) { return BindingEntityInfo.GetClientType(sourceType) .GetProperty(sourceProperty, false) .GetValue(source); } else { return bindingPropertyInfo.PropertyInfo.GetValue(source); } } ///Obtain binding info corresponding to a given type /// Type for which to obtain information ///Info about the private static BindingEntityInfoPerType GetBindingEntityInfoFor(Type entityType) { BindingEntityInfoPerType bindingEntityInfo; metadataCacheLock.EnterReadLock(); try { if (bindingEntityInfos.TryGetValue(entityType, out bindingEntityInfo)) { return bindingEntityInfo; } } finally { metadataCacheLock.ExitReadLock(); } bindingEntityInfo = new BindingEntityInfoPerType(); // Try to get the entity set name from the EntitySetAttribute attributes. In order to make the // inheritance work, we need to look at the attributes declared in the base types also. object[] attributes = entityType.GetCustomAttributes(typeof(EntitySetAttribute), true); // There must be exactly one (unambiguous) EntitySetAttribute attribute. bindingEntityInfo.EntitySet = (attributes != null && attributes.Length == 1) ? ((EntitySetAttribute)attributes[0]).EntitySet : null; bindingEntityInfo.ClientType = ClientType.Create(entityType); foreach (ClientType.ClientProperty p in bindingEntityInfo.ClientType.Properties) { BindingPropertyInfo bpi = null; Type propertyType = p.PropertyType; if (p.CollectionType != null) { if (BindingEntityInfo.IsDataServiceCollection(propertyType)) { bpi = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindCollection }; } } else if (BindingEntityInfo.IsEntityType(propertyType)) { bpi = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindEntity }; } else if (BindingEntityInfo.CanBeComplexProperty(p)) { // Add complex types and nothing else. bpi = new BindingPropertyInfo { PropertyKind = BindingPropertyKind.BindingPropertyKindComplex }; } if (bpi != null) { bpi.PropertyInfo = p; // For complex types only treat complex typed properties as observable, we are not going to observer entity typed or primitive properties. if (bindingEntityInfo.ClientType.IsEntityType || bpi.PropertyKind == BindingPropertyKind.BindingPropertyKindComplex) { bindingEntityInfo.ObservableProperties.Add(bpi); } } } metadataCacheLock.EnterWriteLock(); try { if (!bindingEntityInfos.ContainsKey(entityType)) { bindingEntityInfos[entityType] = bindingEntityInfo; } } finally { metadataCacheLock.ExitWriteLock(); } return bindingEntityInfo; } ///Checks whether a given property can be a complex property i.e. implements INotifyPropertyChanged. /// Input property. ///true if the property is complex property, false otherwise. private static bool CanBeComplexProperty(ClientType.ClientProperty property) { Debug.Assert(property != null, "property != null"); if (typeof(INotifyPropertyChanged).IsAssignableFrom(property.PropertyType)) { Debug.Assert(!property.IsKnownType, "Known types do not implement INotifyPropertyChanged."); return true; } return false; } ///Gets entity set corresponding to a given type /// Intput type ///Entity set name for the type private static string GetEntitySetAttribute(Type entityType) { return GetBindingEntityInfoFor(entityType).EntitySet; } ///Information about a property interesting for binding internal class BindingPropertyInfo { ///Property information public ClientType.ClientProperty PropertyInfo { get; set; } ///Kind of the property i.e. complex, entity or collection. public BindingPropertyKind PropertyKind { get; set; } } ///Holder of information about entity properties for a type private sealed class BindingEntityInfoPerType { ///Collection of properties interesting to the observer private ListobservableProperties; /// Constructor public BindingEntityInfoPerType() { this.observableProperties = new List(); } /// Entity set of the entity public String EntitySet { get; set; } ///Corresponding ClientTyp public ClientType ClientType { get; set; } ///Collection of properties interesting to the observer public ListObservableProperties { get { return this.observableProperties; } } } #if ASTORIA_LIGHT /// Read-writer lock, implemented over a Monitor. private sealed class ReaderWriterLockSlim { ///Single object on which to lock. private object _lock = new object(); ///Enters a reader lock. Writers will also be blocked. internal void EnterReadLock() { Monitor.Enter(_lock); } ///Enters a writer lock. Readers will also be blocked. internal void EnterWriteLock() { Monitor.Enter(_lock); } ///Exits a reader lock. internal void ExitReadLock() { Monitor.Exit(_lock); } ///Exits a writer lock. internal void ExitWriteLock() { Monitor.Exit(_lock); } } #endif } } // 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
- FlowDocumentPage.cs
- DrawItemEvent.cs
- CollectionAdapters.cs
- ExpressionBinding.cs
- DeploymentSectionCache.cs
- DataGridColumnHeader.cs
- FormsAuthentication.cs
- PEFileReader.cs
- Command.cs
- ScriptServiceAttribute.cs
- SchemaImporterExtension.cs
- DefaultAsyncDataDispatcher.cs
- NumericPagerField.cs
- BezierSegment.cs
- TypeDependencyAttribute.cs
- ExternalFile.cs
- Control.cs
- DataKey.cs
- ToolStripGripRenderEventArgs.cs
- HttpDebugHandler.cs
- DelimitedListTraceListener.cs
- SectionInput.cs
- SByte.cs
- panel.cs
- TraceSwitch.cs
- HScrollBar.cs
- SQLInt16.cs
- EntityDataSourceQueryBuilder.cs
- XmlCodeExporter.cs
- DependencyPropertyAttribute.cs
- LeafCellTreeNode.cs
- XmlUrlEditor.cs
- WorkflowOperationBehavior.cs
- FontConverter.cs
- ExecutedRoutedEventArgs.cs
- NameValueConfigurationCollection.cs
- ObjectQuery_EntitySqlExtensions.cs
- BinaryUtilClasses.cs
- NotifyParentPropertyAttribute.cs
- GenericPrincipal.cs
- mediaeventshelper.cs
- WebEventTraceProvider.cs
- DesignerCategoryAttribute.cs
- XmlStreamedByteStreamReader.cs
- DataBindingHandlerAttribute.cs
- BaseDataBoundControl.cs
- RuntimeConfigLKG.cs
- ContainsRowNumberChecker.cs
- TextBox.cs
- TypeReference.cs
- SqlReferenceCollection.cs
- querybuilder.cs
- ParagraphVisual.cs
- Operators.cs
- SafeRightsManagementEnvironmentHandle.cs
- DummyDataSource.cs
- HttpCookiesSection.cs
- PropertySourceInfo.cs
- RecognizedPhrase.cs
- Panel.cs
- ComponentCodeDomSerializer.cs
- FilterableAttribute.cs
- XmlReflectionMember.cs
- SecurityDocument.cs
- CustomErrorCollection.cs
- Nullable.cs
- AppDomainResourcePerfCounters.cs
- TableItemStyle.cs
- PublisherMembershipCondition.cs
- RightsDocument.cs
- AppDomainShutdownMonitor.cs
- TreeChangeInfo.cs
- Validator.cs
- WSTransactionSection.cs
- AdornerLayer.cs
- NumericUpDownAcceleration.cs
- SamlConditions.cs
- ObjectManager.cs
- GridSplitterAutomationPeer.cs
- SqlClientPermission.cs
- UserPreferenceChangedEventArgs.cs
- dtdvalidator.cs
- ImageSourceValueSerializer.cs
- SearchForVirtualItemEventArgs.cs
- _SSPISessionCache.cs
- BoolExpr.cs
- CorrelationToken.cs
- ToolStripGripRenderEventArgs.cs
- GridEntryCollection.cs
- XmlSchemaParticle.cs
- DataPagerFieldCommandEventArgs.cs
- WinEventQueueItem.cs
- TypeDependencyAttribute.cs
- StdRegProviderWrapper.cs
- DoubleAnimationUsingPath.cs
- XmlObjectSerializerReadContextComplexJson.cs
- WebPartTransformer.cs
- RotateTransform3D.cs
- CodeAssignStatement.cs
- PerformanceCounterCategory.cs