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
- OdbcInfoMessageEvent.cs
- PartitionedStream.cs
- TrackingStringDictionary.cs
- ObjectDataSource.cs
- RenderingEventArgs.cs
- InternalControlCollection.cs
- DragDrop.cs
- WebChannelFactory.cs
- MarkedHighlightComponent.cs
- DaylightTime.cs
- PluralizationServiceUtil.cs
- ValidationHelper.cs
- DomainUpDown.cs
- JsonObjectDataContract.cs
- ModelUIElement3D.cs
- DynamicRenderer.cs
- IntegerValidatorAttribute.cs
- IpcChannelHelper.cs
- EventSetter.cs
- BypassElement.cs
- AuthorizationRuleCollection.cs
- TypographyProperties.cs
- XmlSchemaExternal.cs
- TemplatedAdorner.cs
- TextEncodedRawTextWriter.cs
- TextSpanModifier.cs
- ExpressionNode.cs
- ScriptResourceHandler.cs
- ObjectDataSourceDisposingEventArgs.cs
- RedistVersionInfo.cs
- TypedTableBaseExtensions.cs
- GeneralTransform2DTo3D.cs
- WithParamAction.cs
- HttpVersion.cs
- PropertyValueUIItem.cs
- DataGridViewControlCollection.cs
- StringStorage.cs
- XmlRawWriter.cs
- FontDriver.cs
- MimeObjectFactory.cs
- WrapperEqualityComparer.cs
- TextRangeEditLists.cs
- ToolboxBitmapAttribute.cs
- InputLanguageManager.cs
- DropTarget.cs
- XmlDataSourceNodeDescriptor.cs
- EmptyQuery.cs
- InternalConfigHost.cs
- MsmqInputChannelListenerBase.cs
- LayoutTableCell.cs
- TraceContextEventArgs.cs
- SingleStorage.cs
- WorkflowHostingEndpoint.cs
- WebPartVerb.cs
- MappedMetaModel.cs
- VSDExceptions.cs
- CodeTypeConstructor.cs
- FamilyMap.cs
- Assembly.cs
- HtmlElementEventArgs.cs
- Pair.cs
- NumericPagerField.cs
- HtmlInputSubmit.cs
- AuthenticationModuleElementCollection.cs
- DataColumnChangeEvent.cs
- DataGridComboBoxColumn.cs
- Rule.cs
- PopOutPanel.cs
- ImageMapEventArgs.cs
- Parser.cs
- MemberCollection.cs
- StrokeNodeOperations2.cs
- InertiaRotationBehavior.cs
- DefinitionUpdate.cs
- WebPartConnectionsConfigureVerb.cs
- DataControlFieldCell.cs
- CalendarDataBindingHandler.cs
- UniqueEventHelper.cs
- CompatibleComparer.cs
- ClusterSafeNativeMethods.cs
- ConnectionStringSettingsCollection.cs
- StringArrayConverter.cs
- DataGridColumnHeadersPresenter.cs
- BamlStream.cs
- Set.cs
- ConnectionStringsExpressionBuilder.cs
- DefaultPrintController.cs
- SqlDataSourceCommandParser.cs
- ConnectivityStatus.cs
- ChtmlMobileTextWriter.cs
- OperationInvokerTrace.cs
- TableLayoutCellPaintEventArgs.cs
- EntityDesignerUtils.cs
- BoundsDrawingContextWalker.cs
- SiteMapNodeItemEventArgs.cs
- PeerCollaborationPermission.cs
- GrammarBuilderPhrase.cs
- SQLInt16.cs
- StrongNameIdentityPermission.cs
- Label.cs