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
- EventHandlers.cs
- PopupControlService.cs
- MetaTableHelper.cs
- Int64Storage.cs
- mediaeventshelper.cs
- ControlBuilder.cs
- CellParagraph.cs
- Reference.cs
- StrongNameUtility.cs
- regiisutil.cs
- MeasurementDCInfo.cs
- QuaternionIndependentAnimationStorage.cs
- RuntimeConfigLKG.cs
- PropertyDescriptorComparer.cs
- QueryableFilterRepeater.cs
- XXXOnTypeBuilderInstantiation.cs
- RpcResponse.cs
- OleDbTransaction.cs
- QilLoop.cs
- MembershipValidatePasswordEventArgs.cs
- ObjectItemCollection.cs
- UriTemplateMatchException.cs
- TraceData.cs
- StringSource.cs
- AliasExpr.cs
- XamlTemplateSerializer.cs
- PingOptions.cs
- XmlQueryOutput.cs
- _HTTPDateParse.cs
- NonClientArea.cs
- DataPagerFieldCommandEventArgs.cs
- SqlDataReader.cs
- SystemIPGlobalStatistics.cs
- TableCellCollection.cs
- Dictionary.cs
- JumpTask.cs
- TextBreakpoint.cs
- Int16KeyFrameCollection.cs
- EdmProviderManifest.cs
- CqlParser.cs
- ResourceDescriptionAttribute.cs
- AttributeCollection.cs
- SymbolEqualComparer.cs
- ToolStripMenuItem.cs
- StringAnimationUsingKeyFrames.cs
- SystemKeyConverter.cs
- QilGeneratorEnv.cs
- ApplicationFileParser.cs
- DocumentationServerProtocol.cs
- TracingConnectionInitiator.cs
- GridViewRowPresenterBase.cs
- DbMetaDataFactory.cs
- BypassElement.cs
- XmlSerializableWriter.cs
- SslStreamSecurityUpgradeProvider.cs
- HostedTransportConfigurationBase.cs
- TraceEventCache.cs
- OleServicesContext.cs
- MethodExpr.cs
- XmlQueryTypeFactory.cs
- ScriptControl.cs
- CurrentTimeZone.cs
- ValueQuery.cs
- MetadataStore.cs
- RemoteCryptoTokenProvider.cs
- BuilderElements.cs
- AQNBuilder.cs
- ParserExtension.cs
- SafeNativeMethodsCLR.cs
- DataGridViewCellEventArgs.cs
- MouseGestureValueSerializer.cs
- CheckBoxList.cs
- WindowsListViewItemStartMenu.cs
- PolicyDesigner.cs
- HttpContext.cs
- PageWrapper.cs
- PropertyItem.cs
- Nodes.cs
- ElapsedEventArgs.cs
- TableRowCollection.cs
- AffineTransform3D.cs
- UnmanagedBitmapWrapper.cs
- Roles.cs
- BindableAttribute.cs
- WebEvents.cs
- FileDialogCustomPlacesCollection.cs
- ConstraintStruct.cs
- CapabilitiesUse.cs
- XmlSchemaRedefine.cs
- ControlCachePolicy.cs
- DefinitionProperties.cs
- GridViewRowPresenter.cs
- RoutedCommand.cs
- ByteRangeDownloader.cs
- CompilerError.cs
- WebPartConnectionsCloseVerb.cs
- ProtectedConfiguration.cs
- TiffBitmapDecoder.cs
- CheckBox.cs
- ItemCollection.cs