Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- HttpDictionary.cs
- DesignerDeviceConfig.cs
- OdbcPermission.cs
- Trace.cs
- InputManager.cs
- ServicePointManager.cs
- TagNameToTypeMapper.cs
- FlowLayoutPanel.cs
- ValueSerializer.cs
- _DisconnectOverlappedAsyncResult.cs
- KeyFrames.cs
- PropertyDescriptorCollection.cs
- XhtmlBasicValidationSummaryAdapter.cs
- InternalConfigRoot.cs
- FilterException.cs
- IntersectQueryOperator.cs
- ClientConfigurationHost.cs
- MenuItemAutomationPeer.cs
- WriteTimeStream.cs
- DictionarySectionHandler.cs
- HuffModule.cs
- ContainerControl.cs
- CompletionCallbackWrapper.cs
- DataBindingHandlerAttribute.cs
- WebResourceUtil.cs
- DispatchWrapper.cs
- SqlGatherProducedAliases.cs
- TypeForwardedToAttribute.cs
- DispatcherEventArgs.cs
- TdsEnums.cs
- IOException.cs
- ProxyOperationRuntime.cs
- manifestimages.cs
- _NTAuthentication.cs
- CodeTypeConstructor.cs
- RectAnimationBase.cs
- Enum.cs
- IgnoreDeviceFilterElementCollection.cs
- XmlIlTypeHelper.cs
- LeaseManager.cs
- PeerChannelFactory.cs
- TextTabProperties.cs
- PageStatePersister.cs
- UInt32.cs
- CategoryAttribute.cs
- Condition.cs
- RefType.cs
- CategoryNameCollection.cs
- MyContact.cs
- Animatable.cs
- TouchDevice.cs
- SafeNativeMethods.cs
- HtmlInputText.cs
- followingquery.cs
- x509store.cs
- ReadOnlyDictionary.cs
- RoutedCommand.cs
- TableNameAttribute.cs
- WindowsListViewGroupSubsetLink.cs
- ReferencedCollectionType.cs
- CapacityStreamGeometryContext.cs
- PageClientProxyGenerator.cs
- ThreadExceptionEvent.cs
- FrameworkTemplate.cs
- CollectionViewProxy.cs
- ObjectCacheHost.cs
- ParentQuery.cs
- AdCreatedEventArgs.cs
- DisplayClaim.cs
- HttpListenerPrefixCollection.cs
- StructuredType.cs
- BamlReader.cs
- InertiaTranslationBehavior.cs
- ServiceHttpHandlerFactory.cs
- EmptyImpersonationContext.cs
- IncrementalReadDecoders.cs
- XmlParserContext.cs
- ContextDataSourceContextData.cs
- WizardPanelChangingEventArgs.cs
- DecoderFallback.cs
- Pkcs7Recipient.cs
- ValidationPropertyAttribute.cs
- Directory.cs
- MenuItem.cs
- NavigatorOutput.cs
- EncodingFallbackAwareXmlTextWriter.cs
- Sql8ExpressionRewriter.cs
- IconBitmapDecoder.cs
- DetailsView.cs
- ServiceHttpModule.cs
- SoapCommonClasses.cs
- DataBinder.cs
- SecurityContext.cs
- Menu.cs
- Mutex.cs
- PageRanges.cs
- AutoGeneratedField.cs
- PropertyDescriptor.cs
- SizeFConverter.cs
- CompModSwitches.cs