Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DLinq / Dlinq / IdentityManager.cs / 1599186 / IdentityManager.cs
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Security; using System.Security.Permissions; using System.Runtime.CompilerServices; namespace System.Data.Linq { using System.Data.Linq.Mapping; using System.Data.Linq.Provider; internal abstract class IdentityManager { internal abstract object InsertLookup(MetaType type, object instance); internal abstract bool RemoveLike(MetaType type, object instance); internal abstract object Find(MetaType type, object[] keyValues); internal abstract object FindLike(MetaType type, object instance); internal static IdentityManager CreateIdentityManager(bool asReadOnly) { if (asReadOnly) { return new ReadOnlyIdentityManager(); } else { return new StandardIdentityManager(); } } class StandardIdentityManager : IdentityManager { Dictionarycaches; IdentityCache currentCache; MetaType currentType; internal StandardIdentityManager() { this.caches = new Dictionary (); } internal override object InsertLookup(MetaType type, object instance) { this.SetCurrent(type); return this.currentCache.InsertLookup(instance); } internal override bool RemoveLike(MetaType type, object instance) { this.SetCurrent(type); return this.currentCache.RemoveLike(instance); } internal override object Find(MetaType type, object[] keyValues) { this.SetCurrent(type); return this.currentCache.Find(keyValues); } internal override object FindLike(MetaType type, object instance) { this.SetCurrent(type); return this.currentCache.FindLike(instance); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private void SetCurrent(MetaType type) { type = type.InheritanceRoot; if (this.currentType != type) { if (!this.caches.TryGetValue(type, out this.currentCache)) { KeyManager km = GetKeyManager(type); this.currentCache = (IdentityCache)Activator.CreateInstance( typeof(IdentityCache<,>).MakeGenericType(type.Type, km.KeyType), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new object[] { km }, null ); this.caches.Add(type, this.currentCache); } this.currentType = type; } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] static KeyManager GetKeyManager(MetaType type) { int n = type.IdentityMembers.Count; MetaDataMember mm = type.IdentityMembers[0]; KeyManager km = (KeyManager)Activator.CreateInstance( typeof(SingleKeyManager<,>).MakeGenericType(type.Type, mm.Type), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new object[] { mm.StorageAccessor, 0 }, null ); for (int i = 1; i < n; i++) { mm = type.IdentityMembers[i]; km = (KeyManager) Activator.CreateInstance( typeof(MultiKeyManager<,,>).MakeGenericType(type.Type, mm.Type, km.KeyType), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new object[] { mm.StorageAccessor, i, km }, null ); } return km; } #region Nested type definitions // These types are internal rather than private to work around // CLR bug #117419 related to type visibility under partial trust // in nested class scenarios. internal abstract class KeyManager { internal abstract Type KeyType { get; } } internal abstract class KeyManager : KeyManager { internal abstract K CreateKeyFromInstance(T instance); internal abstract bool TryCreateKeyFromValues(object[] values, out K k); internal abstract IEqualityComparer Comparer { get; } } internal class SingleKeyManager : KeyManager { bool isKeyNullAssignable; MetaAccessor accessor; int offset; IEqualityComparer comparer; internal SingleKeyManager(MetaAccessor accessor, int offset) { this.accessor = accessor; this.offset = offset; this.isKeyNullAssignable = System.Data.Linq.SqlClient.TypeSystem.IsNullAssignable(typeof(V)); } internal override V CreateKeyFromInstance(T instance) { return this.accessor.GetValue(instance); } internal override bool TryCreateKeyFromValues(object[] values, out V v) { object o = values[this.offset]; if (o == null && !this.isKeyNullAssignable) { v = default(V); return false; } v = (V)o; return true; } internal override Type KeyType { get { return typeof(V); } } internal override IEqualityComparer Comparer { get { if (this.comparer == null) { this.comparer = EqualityComparer .Default; } return this.comparer; } } } internal class MultiKeyManager : KeyManager > { MetaAccessor accessor; int offset; KeyManager next; IEqualityComparer > comparer; internal MultiKeyManager(MetaAccessor accessor, int offset, KeyManager next) { this.accessor = accessor; this.next = next; this.offset = offset; } internal override MultiKey CreateKeyFromInstance(T instance) { return new MultiKey ( this.accessor.GetValue(instance), this.next.CreateKeyFromInstance(instance) ); } internal override bool TryCreateKeyFromValues(object[] values, out MultiKey k) { System.Diagnostics.Debug.Assert(this.offset < values.Length, "offset is outside the bounds of the values array"); object o = values[this.offset]; if (o == null && typeof(V1).IsValueType) { k = default(MultiKey ); return false; } V2 v2; if (!this.next.TryCreateKeyFromValues(values, out v2)) { k = default(MultiKey ); return false; } k = new MultiKey ((V1)o, v2); return true; } internal override Type KeyType { get { return typeof(MultiKey ); } } internal override IEqualityComparer > Comparer { get { if (this.comparer == null) { this.comparer = new MultiKey .Comparer(EqualityComparer .Default, next.Comparer); } return this.comparer; } } } internal struct MultiKey { T1 value1; T2 value2; internal MultiKey(T1 value1, T2 value2) { this.value1 = value1; this.value2 = value2; } internal class Comparer : IEqualityComparer >, IEqualityComparer { IEqualityComparer comparer1; IEqualityComparer comparer2; internal Comparer(IEqualityComparer comparer1, IEqualityComparer comparer2) { this.comparer1 = comparer1; this.comparer2 = comparer2; } public bool Equals(MultiKey x, MultiKey y) { return this.comparer1.Equals(x.value1, y.value1) && this.comparer2.Equals(x.value2, y.value2); } public int GetHashCode(MultiKey x) { return this.comparer1.GetHashCode(x.value1) ^ this.comparer2.GetHashCode(x.value2); } bool IEqualityComparer.Equals(object x, object y) { return this.Equals((MultiKey )x, (MultiKey )y); } int IEqualityComparer.GetHashCode(object x) { return this.GetHashCode((MultiKey )x); } } } internal abstract class IdentityCache { internal abstract object Find(object[] keyValues); internal abstract object FindLike(object instance); internal abstract object InsertLookup(object instance); internal abstract bool RemoveLike(object instance); } internal class IdentityCache : IdentityCache { int[] buckets; Slot[] slots; int count; int freeList; KeyManager keyManager; IEqualityComparer comparer; public IdentityCache(KeyManager keyManager) { this.keyManager = keyManager; this.comparer = keyManager.Comparer; buckets = new int[7]; slots = new Slot[7]; freeList = -1; } internal override object InsertLookup(object instance) { T value = (T)instance; K key = this.keyManager.CreateKeyFromInstance(value); Find(key, ref value, true); return value; } internal override bool RemoveLike(object instance) { T value = (T)instance; K key = this.keyManager.CreateKeyFromInstance(value); int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; int bucket = hashCode % buckets.Length; int last = -1; for (int i = buckets[bucket] - 1; i >= 0; last = i, i = slots[i].next) { if (slots[i].hashCode == hashCode && comparer.Equals(slots[i].key, key)) { if (last < 0) { buckets[bucket] = slots[i].next + 1; } else { slots[last].next = slots[i].next; } slots[i].hashCode = -1; slots[i].value = default(T); slots[i].next = freeList; freeList = i; return true; } } return false; } internal override object Find(object[] keyValues) { K key; if (this.keyManager.TryCreateKeyFromValues(keyValues, out key)) { T value = default(T); if (Find(key, ref value, false)) return value; } return null; } internal override object FindLike(object instance) { T value = (T)instance; K key = this.keyManager.CreateKeyFromInstance(value); if (Find(key, ref value, false)) return value; return null; } bool Find(K key, ref T value, bool add) { int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; for (int i = buckets[hashCode % buckets.Length] - 1; i >= 0; i = slots[i].next) { if (slots[i].hashCode == hashCode && comparer.Equals(slots[i].key, key)) { value = slots[i].value; return true; } } if (add) { int index; if (freeList >= 0) { index = freeList; freeList = slots[index].next; } else { if (count == slots.Length) Resize(); index = count; count++; } int bucket = hashCode % buckets.Length; slots[index].hashCode = hashCode; slots[index].key = key; slots[index].value = value; slots[index].next = buckets[bucket] - 1; buckets[bucket] = index + 1; } return false; } void Resize() { int newSize = checked(count * 2 + 1); int[] newBuckets = new int[newSize]; Slot[] newSlots = new Slot[newSize]; Array.Copy(slots, 0, newSlots, 0, count); for (int i = 0; i < count; i++) { int bucket = newSlots[i].hashCode % newSize; newSlots[i].next = newBuckets[bucket] - 1; newBuckets[bucket] = i + 1; } buckets = newBuckets; slots = newSlots; } internal struct Slot { internal int hashCode; internal K key; internal T value; internal int next; } } #endregion } /// /// This is the noop implementation used when object tracking is disabled. /// class ReadOnlyIdentityManager : IdentityManager { internal ReadOnlyIdentityManager() { } internal override object InsertLookup(MetaType type, object instance) { return instance; } internal override bool RemoveLike(MetaType type, object instance) { return false; } internal override object Find(MetaType type, object[] keyValues) { return null; } internal override object FindLike(MetaType type, object instance) { return null; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TrustSection.cs
- Calendar.cs
- DynamicRenderer.cs
- XmlComment.cs
- ObjectStorage.cs
- KeySpline.cs
- ConstraintManager.cs
- __ComObject.cs
- SystemIPInterfaceStatistics.cs
- IsolatedStorageFileStream.cs
- MediaContext.cs
- ValidationManager.cs
- MenuItemStyle.cs
- IOException.cs
- HttpWebRequestElement.cs
- XmlNodeList.cs
- TransformProviderWrapper.cs
- FileAuthorizationModule.cs
- WebBrowserHelper.cs
- Substitution.cs
- XmlUtf8RawTextWriter.cs
- HttpWriter.cs
- OneOf.cs
- RecipientServiceModelSecurityTokenRequirement.cs
- _Win32.cs
- InstanceCreationEditor.cs
- AnimatedTypeHelpers.cs
- XmlWrappingReader.cs
- TabItemAutomationPeer.cs
- FontNamesConverter.cs
- ProfileModule.cs
- ADRole.cs
- XmlUrlResolver.cs
- Base64Encoder.cs
- CheckableControlBaseAdapter.cs
- _SecureChannel.cs
- SignedXml.cs
- EncryptedType.cs
- VectorCollectionConverter.cs
- XslException.cs
- ResizingMessageFilter.cs
- Visual3D.cs
- DataGridDefaultColumnWidthTypeConverter.cs
- HwndSubclass.cs
- Codec.cs
- TextSchema.cs
- ArithmeticException.cs
- ZoneButton.cs
- WebPartConnectionCollection.cs
- safex509handles.cs
- ExtensionSurface.cs
- ResourceAssociationSetEnd.cs
- StyleTypedPropertyAttribute.cs
- TypefaceMap.cs
- MemberPath.cs
- WebPartManagerInternals.cs
- Wrapper.cs
- NodeFunctions.cs
- RoleServiceManager.cs
- XmlElementAttribute.cs
- ObjectQueryState.cs
- AlternationConverter.cs
- TableParaClient.cs
- TableRowGroup.cs
- WebPartActionVerb.cs
- MgmtResManager.cs
- DecimalConstantAttribute.cs
- ListenerServiceInstallComponent.cs
- UrlMappingsModule.cs
- RegexCharClass.cs
- ParameterToken.cs
- ProviderSettings.cs
- CommandSet.cs
- OutputCacheSettingsSection.cs
- PreviewPrintController.cs
- PrivilegedConfigurationManager.cs
- ViewBox.cs
- NavigationEventArgs.cs
- XmlReader.cs
- ModelItemCollection.cs
- FieldCollectionEditor.cs
- AnonymousIdentificationSection.cs
- PnrpPermission.cs
- SoapTypeAttribute.cs
- MultiByteCodec.cs
- TimeEnumHelper.cs
- HashAlgorithm.cs
- ContentType.cs
- KeyFrames.cs
- DataGridViewEditingControlShowingEventArgs.cs
- TdsParserSessionPool.cs
- MaskedTextBox.cs
- WindowsScrollBarBits.cs
- Point.cs
- DeobfuscatingStream.cs
- SweepDirectionValidation.cs
- UTF7Encoding.cs
- Validator.cs
- AutomationIdentifier.cs
- SQLInt16.cs