Types.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DLinq / Dlinq / Types.cs / 1 / Types.cs

                            using System; 
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions; 
using System.IO;
using System.Linq; 
using System.Reflection; 
using System.Text;
using System.Diagnostics; 
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;

namespace System.Data.Linq { 
    internal static class SourceState {
        internal static readonly IEnumerable Loaded = (IEnumerable)new T[] { }; 
        internal static readonly IEnumerable Assigned = (IEnumerable)new T[] { }; 
    }
 
    [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "[....]: Types are never compared to each other.  When comparisons happen it is against the entities that are represented by these constructs.")]
    public struct Link {
        T underlyingValue;
        IEnumerable source; 

        public Link(T value) { 
            this.underlyingValue = value; 
            this.source = null;
        } 

        public Link(IEnumerable source) {
            this.source = source;
            this.underlyingValue = default(T); 
        }
 
        public Link(Link link) { 
            this.underlyingValue = link.underlyingValue;
            this.source = link.source; 
        }

        public bool HasValue {
            get { return this.source == null || this.HasLoadedValue || this.HasAssignedValue; } 
        }
 
        public bool HasLoadedOrAssignedValue { 
            get { return this.HasLoadedValue || this.HasAssignedValue; }
        } 

        internal bool HasLoadedValue {
            get { return this.source == SourceState.Loaded; }
        } 

        internal bool HasAssignedValue { 
            get { return this.source == SourceState.Assigned; } 
        }
 
        internal T UnderlyingValue {
            get { return this.underlyingValue; }
        }
 
        internal IEnumerable Source {
            get { return this.source; } 
        } 

        internal bool HasSource { 
            get { return this.source != null && !this.HasAssignedValue && !this.HasLoadedValue; }
        }

        public T Value { 
            get {
                if (this.HasSource) { 
                    this.underlyingValue = Enumerable.SingleOrDefault(this.source); 
                    this.source = SourceState.Loaded;
                } 
                return this.underlyingValue;
            }
            set {
                this.underlyingValue = value; 
                this.source = SourceState.Assigned;
            } 
        } 
    }
 
    [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification="[....]: Types are never compared to each other.  When comparisons happen it is against the entities that are represented by these constructs.")]
    public struct EntityRef
        where TEntity : class {
        IEnumerable source; 
        TEntity entity;
 
        public EntityRef(TEntity entity) { 
            this.entity = entity;
            this.source = SourceState.Assigned; 
        }

        public EntityRef(IEnumerable source) {
            this.source = source; 
            this.entity = default(TEntity);
        } 
 
        public EntityRef(EntityRef entityRef) {
            this.source = entityRef.source; 
            this.entity = entityRef.entity;
        }

        public TEntity Entity { 
            get {
                if (this.HasSource) { 
 
                    IEnumerable src = this.source;
                    this.entity = Enumerable.SingleOrDefault(src); 
                    this.source = SourceState.Loaded;
                }
                return this.entity;
            } 
            set {
                this.entity = value; 
                this.source = SourceState.Assigned; 
            }
        } 

        public bool HasLoadedOrAssignedValue {
            get { return this.HasLoadedValue || this.HasAssignedValue; }
        } 

        internal bool HasValue { 
            get { return this.source == null || this.HasLoadedValue || this.HasAssignedValue; } 
        }
 
        internal bool HasLoadedValue {
            get { return this.source == SourceState.Loaded; }
        }
 
        internal bool HasAssignedValue {
            get { return this.source == SourceState.Assigned; } 
        } 

        internal bool HasSource { 
            get { return this.source != null && !this.HasLoadedValue && !this.HasAssignedValue; }
        }

        internal IEnumerable Source { 
            get { return this.source; }
        } 
 
        internal TEntity UnderlyingValue {
            get { return this.entity; } 
        }
    }

    [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification="[....]: Naming chosen to represent a different concept from a collection because it is delayed loaded.")] 
    public sealed class EntitySet : IList, IList, IListSource
        where TEntity : class { 
        IEnumerable source; 
        ItemList entities;
        ItemList removedEntities; 
        Action onAdd;
        Action onRemove;
        TEntity onAddEntity;
        TEntity onRemoveEntity; 
        int version;
        private ListChangedEventHandler onListChanged; 
        private bool isModified; 
        private bool isLoaded;
        bool listChanged; 

        public EntitySet() {
        }
 
        public EntitySet(Action onAdd, Action onRemove) {
            this.onAdd = onAdd; 
            this.onRemove = onRemove; 
        }
 
        internal EntitySet(EntitySet es, bool copyNotifications) {
            this.source = es.source;
            foreach (TEntity e in es.entities) entities.Add(e);
            foreach (TEntity e in es.removedEntities) removedEntities.Add(e); 
            this.version = es.version;
            if (copyNotifications) { 
                this.onAdd = es.onAdd; 
                this.onRemove = es.onRemove;
            } 
        }

        public int Count {
            get { 
                Load();
                return entities.Count; 
            } 
        }
 
        public TEntity this[int index] {
            get {
                Load();
                if (index < 0 || index >= entities.Count) 
                    throw Error.ArgumentOutOfRange("index");
                return entities[index]; 
            } 
            set {
                Load(); 
                if (index < 0 || index >= entities.Count)
                    throw Error.ArgumentOutOfRange("index");
                if (value == null || IndexOf(value) >= 0)
                    throw Error.ArgumentOutOfRange("value"); 
                CheckModify();
                TEntity old = entities[index]; 
                OnRemove(old); 
                OnListChanged(ListChangedType.ItemDeleted, index);
 
                OnAdd(value);
                entities[index] = value;
                OnModified();
                OnListChanged(ListChangedType.ItemAdded, index); 
            }
        } 
 
        [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")]
        public void Add(TEntity entity) { 
            if (entity == null) {
                throw Error.ArgumentNull("entity");
            }
            if (entity != onAddEntity) { 
                CheckModify();
                if (!entities.Contains(entity)) { 
                    OnAdd(entity); 
                    if (this.HasSource) removedEntities.Remove(entity);
                    entities.Add(entity); 
                    if (this.IsLoaded) {
                        OnListChanged(ListChangedType.ItemAdded, IndexOf(entity));
                    }
                } 
                OnModified();
            } 
        } 

        public void AddRange(IEnumerable collection) { 
            if (collection == null)
                throw Error.ArgumentNull("collection");
            CheckModify();
            // convert to List in case adding elements here removes them from the 'collection' (ie entityset to entityset assignment) 
            collection = collection.ToList();
            foreach (TEntity e in collection) { 
                if (!entities.Contains(e)) { 
                    OnAdd(e);
                    if (this.HasSource) removedEntities.Remove(e); 
                    entities.Add(e);
                    if (this.IsLoaded){
                        OnListChanged(ListChangedType.ItemAdded, IndexOf(e));
                    } 
                }
            } 
            OnModified(); 
        }
 
        public void Assign(IEnumerable entitySource) {
            Clear();
            if (entitySource != null)
                AddRange(entitySource); 

            // When an entity set is assigned, it is considered loaded. 
            // Since with defer loading enabled, a load is triggered 
            // anyways, this is only necessary in cases where defer loading
            // is disabled.  In such cases, the materializer assigns a 
            // prefetched collection and we want IsLoaded to be true.
            this.isLoaded = true;
        }
 
        public void Clear() {
            Load(); 
            CheckModify(); 
            if (entities.Items != null) {
                List removeList = new List(entities.Items); 
                foreach (TEntity e in removeList) {
                    Remove(e);
                }
            } 
            entities = default(ItemList);
            OnModified(); 
            OnListChanged(ListChangedType.Reset, 0); 
        }
 
        [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")]
        public bool Contains(TEntity entity) {
            return IndexOf(entity) >= 0;
        } 

        public void CopyTo(TEntity[] array, int arrayIndex) { 
            Load(); 
            if (entities.Count > 0) Array.Copy(entities.Items, 0, array, arrayIndex, entities.Count);
        } 

        public IEnumerator GetEnumerator() {
            Load();
            return new Enumerator(this); 
        }
 
        internal IEnumerable GetUnderlyingValues() { 
            return new UnderlyingValues(this);
        } 

        class UnderlyingValues : IEnumerable {
            EntitySet entitySet;
            internal UnderlyingValues(EntitySet entitySet) { 
                this.entitySet = entitySet;
            } 
            public IEnumerator GetEnumerator() { 
                return new Enumerator(this.entitySet);
            } 
            IEnumerator IEnumerable.GetEnumerator() {
                return this.GetEnumerator();
            }
        } 

        [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")] 
        public int IndexOf(TEntity entity) { 
            Load();
            return entities.IndexOf(entity); 
        }

        [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "1#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")]
        public void Insert(int index, TEntity entity) { 
            Load();
            if (index < 0 || index > Count) 
                throw Error.ArgumentOutOfRange("index"); 
            if (entity == null || IndexOf(entity) >= 0)
                throw Error.ArgumentOutOfRange("entity"); 
            CheckModify();
            entities.Insert(index, entity);
            OnListChanged(ListChangedType.ItemAdded, index);
 
            OnAdd(entity);
        } 
 
        /// 
        /// Returns true if this entity set has a deferred query 
        /// that hasn't been executed yet.
        /// 
        public bool IsDeferred
        { 
            get { return HasSource; }
        } 
 
        /// 
        /// Returns true if values have been either assigned or loaded. 
        /// 
        internal bool HasValues {
            get { return this.source == null || this.HasAssignedValues || this.HasLoadedValues; }
        } 

        ///  
        /// Returns true if the entity set has been modified in any way by the user or its items 
        /// have been loaded from the database.
        ///  
        public bool HasLoadedOrAssignedValues {
            get { return this.HasAssignedValues || this.HasLoadedValues; }
        }
 
        /// 
        /// Returns true if the set has been modified in any way by the user. 
        ///  
        internal bool HasAssignedValues {
            get { return this.isModified; } 
        }

        /// 
        /// Returns true if the set has been loaded from the database. 
        /// 
        internal bool HasLoadedValues { 
            get { return this.isLoaded; } 
        }
 
        /// 
        /// Returns true if the set has a deferred source query that hasn't been loaded yet.
        /// 
        internal bool HasSource { 
            get { return this.source != null && !this.HasLoadedValues; }
        } 
 
        /// 
        /// Returns true if the collection has been loaded. 
        /// 
        internal bool IsLoaded {
            get {
                return this.isLoaded; 
            }
        } 
 
        internal IEnumerable Source {
            get { return this.source; } 
        }

        public void Load() {
            if (this.HasSource) { 
                ItemList addedEntities = entities;
                entities = default(ItemList); 
                foreach (TEntity e in source) entities.Add(e); 
                foreach (TEntity e in addedEntities) entities.Include(e);
                foreach (TEntity e in removedEntities) entities.Remove(e); 
                source = SourceState.Loaded;
                isLoaded = true;
                removedEntities = default(ItemList);
            } 
        }
 
        private void OnModified() { 
            isModified = true;
        } 

        [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")]
        public bool Remove(TEntity entity) {
            if (entity == null || entity == onRemoveEntity) return false; 
            CheckModify();
            int index = -1; 
            bool removed = false; 
            if (this.HasSource) {
                if (!removedEntities.Contains(entity)) { 
                    OnRemove(entity);
                    // check in entities in case it has been pre-added
                    index = entities.IndexOf(entity);
                    if (index != -1) { 
                        entities.RemoveAt(index);
                    } 
                    else { 
                        removedEntities.Add(entity);
                    } 
                    removed = true;
                }
            } else {
                index = entities.IndexOf(entity); 
                if (index != -1) {
                    OnRemove(entity); 
                    entities.RemoveAt(index); 
                    removed = true;
                } 
            }
            if (removed) {
                OnModified();
                if (this.IsLoaded) { 
                    System.Diagnostics.Debug.Assert(index != -1);
                    OnListChanged(ListChangedType.ItemDeleted, index); 
                } 
            }
            return removed; 
        }

        public void RemoveAt(int index) {
            Load(); 
            if (index < 0 || index >= Count) {
                throw Error.ArgumentOutOfRange("index"); 
            } 
            CheckModify();
            TEntity entity = entities[index]; 
            OnRemove(entity);
            entities.RemoveAt(index);
            OnModified();
            OnListChanged(ListChangedType.ItemDeleted, index); 
        }
 
        public void SetSource(IEnumerable entitySource) { 
            if (this.HasAssignedValues || this.HasLoadedValues)
                throw Error.EntitySetAlreadyLoaded(); 
            this.source = entitySource;
        }

        void CheckModify() { 
            if (onAddEntity != null || onRemoveEntity != null)
                throw Error.ModifyDuringAddOrRemove(); 
            version++; 
        }
 
        void OnAdd(TEntity entity) {
            if (onAdd != null) {
                TEntity e = onAddEntity;
                onAddEntity = entity; 
                try {
                    onAdd(entity); 
                } finally { 
                    onAddEntity = e;
                } 
            }
        }

        void OnRemove(TEntity entity) { 
            if (onRemove != null) {
                TEntity e = onRemoveEntity; 
                onRemoveEntity = entity; 
                try {
                    onRemove(entity); 
                } finally {
                    onRemoveEntity = e;
                }
            } 
        }
 
        class Enumerable : IEnumerable { 
            EntitySet entitySet;
            public Enumerable(EntitySet entitySet) { 
                this.entitySet = entitySet;
            }
            IEnumerator IEnumerable.GetEnumerator() {
                return this.GetEnumerator(); 
            }
            public IEnumerator GetEnumerator() { 
                return new Enumerator(this.entitySet); 
            }
        } 

        class Enumerator : IEnumerator {
            EntitySet entitySet;
            TEntity[] items; 
            int index;
            int endIndex; 
            int version; 

            public Enumerator(EntitySet entitySet) { 
                this.entitySet = entitySet;
                this.items = entitySet.entities.Items;
                this.index = -1;
                this.endIndex = entitySet.entities.Count - 1; 
                this.version = entitySet.version;
            } 
 
            public void Dispose() { }
 
            public bool MoveNext() {
                if (version != entitySet.version)
                    throw Error.EntitySetModifiedDuringEnumeration();
                if (index == endIndex) return false; 
                index++;
                return true; 
            } 

            public TEntity Current { 
                get { return items[index]; }
            }

            object IEnumerator.Current { 
                get { return items[index]; }
            } 
 
            void IEnumerator.Reset() {
                if (version != entitySet.version) 
                    throw Error.EntitySetModifiedDuringEnumeration();
                index = -1;
            }
        } 

        int IList.Add(object value) { 
            TEntity entity = value as TEntity; 
            if (entity == null || IndexOf(entity) >= 0) {
                throw Error.ArgumentOutOfRange("value"); 
            }
            CheckModify();
            int i = entities.Count;
            entities.Add(entity); 
            OnAdd(entity);
            return i; 
        } 

        bool IList.Contains(object value) { 
            return Contains(value as TEntity);
        }

        int IList.IndexOf(object value) { 
            return IndexOf(value as TEntity);
        } 
 
        void IList.Insert(int index, object value) {
            TEntity entity = value as TEntity; 
            if (value == null)
                throw Error.ArgumentOutOfRange("value");
            Insert(index, entity);
        } 

        bool IList.IsFixedSize { 
            get { return false; } 
        }
 
        bool IList.IsReadOnly {
            get { return false; }
        }
 
        void IList.Remove(object value) {
            Remove(value as TEntity); 
        } 

        object IList.this[int index] { 
            get {
                return this[index];
            }
            set { 
                TEntity entity = value as TEntity;
                if (value == null) throw Error.ArgumentOutOfRange("value"); 
                this[index] = entity; 
            }
        } 

        void ICollection.CopyTo(Array array, int index) {
            Load();
            if (entities.Count > 0) Array.Copy(entities.Items, 0, array, index, entities.Count); 
        }
 
        bool ICollection.IsSynchronized { 
            get { return false; }
        } 

        object ICollection.SyncRoot {
            get { return this; }
        } 

        bool ICollection.IsReadOnly { 
            get { return false; } 
        }
 
        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator();
        }
 
        void OnListChanged(ListChangedType type, int index) {
            listChanged = true; 
            if (onListChanged != null) { 
                onListChanged(this, new ListChangedEventArgs(type, index));
            } 
        }

        public event ListChangedEventHandler ListChanged {
            add { 
                onListChanged += value;
            } 
            remove { 
                onListChanged -= value;
            } 
        }

        bool IListSource.ContainsListCollection {
            get { return true; } 
        }
 
        private IBindingList cachedList = null; 

        IList IListSource.GetList() { 
            if (cachedList == null || listChanged) {
                cachedList = GetNewBindingList();
                listChanged = false;
            } 
            return cachedList;
        } 
 
        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification="Method doesn't represent a property of the type.")]
        public IBindingList GetNewBindingList() { 
            return new EntitySetBindingList(this.ToList(), this);
        }
    }
 
    struct ItemList where T : class {
        T[] items; 
        int count; 

        public int Count { 
            get { return count; }
        }

        public T[] Items { 
            get { return items; }
        } 
 
        public T this[int index] {
            get { return items[index]; } 
            set { items[index] = value; }
        }

        public void Add(T item) { 
            if (items == null || items.Length == count) GrowItems();
            items[count] = item; 
            count++; 
        }
 
        public bool Contains(T item) {
            return IndexOf(item) >= 0;
        }
 
        public Enumerator GetEnumerator() {
            Enumerator e; 
            e.items = items; 
            e.index = -1;
            e.endIndex = count - 1; 
            return e;
        }

        public bool Include(T item) { 
            if (LastIndexOf(item) >= 0) return false;
            Add(item); 
            return true; 
        }
 
        public int IndexOf(T item) {
            for (int i = 0; i < count; i++) {
                if (items[i] == item) return i;
            } 
            return -1;
        } 
 
        public void Insert(int index, T item) {
            if (items == null || items.Length == count) GrowItems(); 
            if (index < count) Array.Copy(items, index, items, index + 1, count - index);
            items[index] = item;
            count++;
        } 

        public int LastIndexOf(T item) { 
            int i = count; 
            while (i > 0) {
                --i; 
                if (items[i] == item) return i;
            }
            return -1;
        } 

        public bool Remove(T item) { 
            int i = IndexOf(item); 
            if (i < 0) return false;
            RemoveAt(i); 
            return true;
        }

        public void RemoveAt(int index) { 
            count--;
            if (index < count) Array.Copy(items, index + 1, items, index, count - index); 
            items[count] = default(T); 
        }
 
        void GrowItems() {
            Array.Resize(ref items, count == 0 ? 4 : count * 2);
        }
 
        public struct Enumerator {
            internal T[] items; 
            internal int index; 
            internal int endIndex;
 
            public bool MoveNext() {
                if (index == endIndex) return false;
                index++;
                return true; 
            }
 
            public T Current { 
                get { return items[index]; }
            } 
        }
    }

    [SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces", Justification = "[....]: The name clearly describes function and the namespace is under a DLinq namespace which will make the distinction clear.")] 
    [DataContract]
    [Serializable] 
    public sealed class Binary : IEquatable { 
        [DataMember(Name="Bytes")]
        byte[] bytes; 
        int? hashCode;

        public Binary(byte[] value) {
            if (value == null) 
                throw Error.ArgumentNull("value");
            this.bytes = new byte[value.Length]; 
            Array.Copy(value, this.bytes, value.Length); 
            this.ComputeHash();
        } 

        public byte[] ToArray() {
            byte[] copy = new byte[this.bytes.Length];
            Array.Copy(this.bytes, copy, copy.Length); 
            return copy;
        } 
 
        public int Length {
            get { return this.bytes.Length; } 
        }

        public static implicit operator Binary(byte[] value) {
            return new Binary(value); 
        }
 
        public bool Equals(Binary other) { 
            return this.EqualsTo(other);
        } 

        public static bool operator ==(Binary binary1, Binary binary2) {
            if ((object)binary1 == (object)binary2)
                return true; 
            if ((object)binary1 == null && (object)binary2 == null)
                return true; 
            if ((object)binary1 == null || (object)binary2 == null) 
                return false;
            return binary1.EqualsTo(binary2); 
        }

        public static bool operator !=(Binary binary1, Binary binary2) {
            if ((object)binary1 == (object)binary2) 
                return false;
            if ((object)binary1 == null && (object)binary2 == null) 
                return false; 
            if ((object)binary1 == null || (object)binary2 == null)
                return true; 
            return !binary1.EqualsTo(binary2);
        }

        public override bool Equals(object obj) { 
            return this.EqualsTo(obj as Binary);
        } 
 
        public override int GetHashCode() {
            if (!hashCode.HasValue) { 
                // hash code is not marked [DataMember], so when
                // using the DataContractSerializer, we'll need
                // to recompute the hash after deserialization.
                ComputeHash(); 
            }
            return this.hashCode.Value; 
        } 

        public override string ToString() { 
            StringBuilder sb = new StringBuilder();
            sb.Append("\"");
            sb.Append(System.Convert.ToBase64String(this.bytes, 0, this.bytes.Length));
            sb.Append("\""); 
            return sb.ToString();
        } 
 
        private bool EqualsTo(Binary binary) {
            if ((object)this == (object)binary) 
                return true;
            if ((object)binary == null)
                return false;
            if (this.bytes.Length != binary.bytes.Length) 
                return false;
            if (this.hashCode != binary.hashCode) 
                return false; 
            for (int i = 0, n = this.bytes.Length; i < n; i++) {
                if (this.bytes[i] != binary.bytes[i]) 
                    return false;
            }
            return true;
        } 

        ///  
        /// Simple hash using pseudo-random coefficients for each byte in 
        /// the array to achieve order dependency.
        ///  
        private void ComputeHash() {
            int s = 314, t = 159;
            hashCode = 0;
            for (int i = 0; i < bytes.Length; i++) { 
                hashCode = hashCode * s + bytes[i];
                s = s * t; 
            } 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
´╗┐using System; 
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions; 
using System.IO;
using System.Linq; 
using System.Reflection; 
using System.Text;
using System.Diagnostics; 
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;

namespace System.Data.Linq { 
    internal static class SourceState {
        internal static readonly IEnumerable Loaded = (IEnumerable)new T[] { }; 
        internal static readonly IEnumerable Assigned = (IEnumerable)new T[] { }; 
    }
 
    [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "[....]: Types are never compared to each other.  When comparisons happen it is against the entities that are represented by these constructs.")]
    public struct Link {
        T underlyingValue;
        IEnumerable source; 

        public Link(T value) { 
            this.underlyingValue = value; 
            this.source = null;
        } 

        public Link(IEnumerable source) {
            this.source = source;
            this.underlyingValue = default(T); 
        }
 
        public Link(Link link) { 
            this.underlyingValue = link.underlyingValue;
            this.source = link.source; 
        }

        public bool HasValue {
            get { return this.source == null || this.HasLoadedValue || this.HasAssignedValue; } 
        }
 
        public bool HasLoadedOrAssignedValue { 
            get { return this.HasLoadedValue || this.HasAssignedValue; }
        } 

        internal bool HasLoadedValue {
            get { return this.source == SourceState.Loaded; }
        } 

        internal bool HasAssignedValue { 
            get { return this.source == SourceState.Assigned; } 
        }
 
        internal T UnderlyingValue {
            get { return this.underlyingValue; }
        }
 
        internal IEnumerable Source {
            get { return this.source; } 
        } 

        internal bool HasSource { 
            get { return this.source != null && !this.HasAssignedValue && !this.HasLoadedValue; }
        }

        public T Value { 
            get {
                if (this.HasSource) { 
                    this.underlyingValue = Enumerable.SingleOrDefault(this.source); 
                    this.source = SourceState.Loaded;
                } 
                return this.underlyingValue;
            }
            set {
                this.underlyingValue = value; 
                this.source = SourceState.Assigned;
            } 
        } 
    }
 
    [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification="[....]: Types are never compared to each other.  When comparisons happen it is against the entities that are represented by these constructs.")]
    public struct EntityRef
        where TEntity : class {
        IEnumerable source; 
        TEntity entity;
 
        public EntityRef(TEntity entity) { 
            this.entity = entity;
            this.source = SourceState.Assigned; 
        }

        public EntityRef(IEnumerable source) {
            this.source = source; 
            this.entity = default(TEntity);
        } 
 
        public EntityRef(EntityRef entityRef) {
            this.source = entityRef.source; 
            this.entity = entityRef.entity;
        }

        public TEntity Entity { 
            get {
                if (this.HasSource) { 
 
                    IEnumerable src = this.source;
                    this.entity = Enumerable.SingleOrDefault(src); 
                    this.source = SourceState.Loaded;
                }
                return this.entity;
            } 
            set {
                this.entity = value; 
                this.source = SourceState.Assigned; 
            }
        } 

        public bool HasLoadedOrAssignedValue {
            get { return this.HasLoadedValue || this.HasAssignedValue; }
        } 

        internal bool HasValue { 
            get { return this.source == null || this.HasLoadedValue || this.HasAssignedValue; } 
        }
 
        internal bool HasLoadedValue {
            get { return this.source == SourceState.Loaded; }
        }
 
        internal bool HasAssignedValue {
            get { return this.source == SourceState.Assigned; } 
        } 

        internal bool HasSource { 
            get { return this.source != null && !this.HasLoadedValue && !this.HasAssignedValue; }
        }

        internal IEnumerable Source { 
            get { return this.source; }
        } 
 
        internal TEntity UnderlyingValue {
            get { return this.entity; } 
        }
    }

    [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification="[....]: Naming chosen to represent a different concept from a collection because it is delayed loaded.")] 
    public sealed class EntitySet : IList, IList, IListSource
        where TEntity : class { 
        IEnumerable source; 
        ItemList entities;
        ItemList removedEntities; 
        Action onAdd;
        Action onRemove;
        TEntity onAddEntity;
        TEntity onRemoveEntity; 
        int version;
        private ListChangedEventHandler onListChanged; 
        private bool isModified; 
        private bool isLoaded;
        bool listChanged; 

        public EntitySet() {
        }
 
        public EntitySet(Action onAdd, Action onRemove) {
            this.onAdd = onAdd; 
            this.onRemove = onRemove; 
        }
 
        internal EntitySet(EntitySet es, bool copyNotifications) {
            this.source = es.source;
            foreach (TEntity e in es.entities) entities.Add(e);
            foreach (TEntity e in es.removedEntities) removedEntities.Add(e); 
            this.version = es.version;
            if (copyNotifications) { 
                this.onAdd = es.onAdd; 
                this.onRemove = es.onRemove;
            } 
        }

        public int Count {
            get { 
                Load();
                return entities.Count; 
            } 
        }
 
        public TEntity this[int index] {
            get {
                Load();
                if (index < 0 || index >= entities.Count) 
                    throw Error.ArgumentOutOfRange("index");
                return entities[index]; 
            } 
            set {
                Load(); 
                if (index < 0 || index >= entities.Count)
                    throw Error.ArgumentOutOfRange("index");
                if (value == null || IndexOf(value) >= 0)
                    throw Error.ArgumentOutOfRange("value"); 
                CheckModify();
                TEntity old = entities[index]; 
                OnRemove(old); 
                OnListChanged(ListChangedType.ItemDeleted, index);
 
                OnAdd(value);
                entities[index] = value;
                OnModified();
                OnListChanged(ListChangedType.ItemAdded, index); 
            }
        } 
 
        [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")]
        public void Add(TEntity entity) { 
            if (entity == null) {
                throw Error.ArgumentNull("entity");
            }
            if (entity != onAddEntity) { 
                CheckModify();
                if (!entities.Contains(entity)) { 
                    OnAdd(entity); 
                    if (this.HasSource) removedEntities.Remove(entity);
                    entities.Add(entity); 
                    if (this.IsLoaded) {
                        OnListChanged(ListChangedType.ItemAdded, IndexOf(entity));
                    }
                } 
                OnModified();
            } 
        } 

        public void AddRange(IEnumerable collection) { 
            if (collection == null)
                throw Error.ArgumentNull("collection");
            CheckModify();
            // convert to List in case adding elements here removes them from the 'collection' (ie entityset to entityset assignment) 
            collection = collection.ToList();
            foreach (TEntity e in collection) { 
                if (!entities.Contains(e)) { 
                    OnAdd(e);
                    if (this.HasSource) removedEntities.Remove(e); 
                    entities.Add(e);
                    if (this.IsLoaded){
                        OnListChanged(ListChangedType.ItemAdded, IndexOf(e));
                    } 
                }
            } 
            OnModified(); 
        }
 
        public void Assign(IEnumerable entitySource) {
            Clear();
            if (entitySource != null)
                AddRange(entitySource); 

            // When an entity set is assigned, it is considered loaded. 
            // Since with defer loading enabled, a load is triggered 
            // anyways, this is only necessary in cases where defer loading
            // is disabled.  In such cases, the materializer assigns a 
            // prefetched collection and we want IsLoaded to be true.
            this.isLoaded = true;
        }
 
        public void Clear() {
            Load(); 
            CheckModify(); 
            if (entities.Items != null) {
                List removeList = new List(entities.Items); 
                foreach (TEntity e in removeList) {
                    Remove(e);
                }
            } 
            entities = default(ItemList);
            OnModified(); 
            OnListChanged(ListChangedType.Reset, 0); 
        }
 
        [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")]
        public bool Contains(TEntity entity) {
            return IndexOf(entity) >= 0;
        } 

        public void CopyTo(TEntity[] array, int arrayIndex) { 
            Load(); 
            if (entities.Count > 0) Array.Copy(entities.Items, 0, array, arrayIndex, entities.Count);
        } 

        public IEnumerator GetEnumerator() {
            Load();
            return new Enumerator(this); 
        }
 
        internal IEnumerable GetUnderlyingValues() { 
            return new UnderlyingValues(this);
        } 

        class UnderlyingValues : IEnumerable {
            EntitySet entitySet;
            internal UnderlyingValues(EntitySet entitySet) { 
                this.entitySet = entitySet;
            } 
            public IEnumerator GetEnumerator() { 
                return new Enumerator(this.entitySet);
            } 
            IEnumerator IEnumerable.GetEnumerator() {
                return this.GetEnumerator();
            }
        } 

        [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")] 
        public int IndexOf(TEntity entity) { 
            Load();
            return entities.IndexOf(entity); 
        }

        [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "1#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")]
        public void Insert(int index, TEntity entity) { 
            Load();
            if (index < 0 || index > Count) 
                throw Error.ArgumentOutOfRange("index"); 
            if (entity == null || IndexOf(entity) >= 0)
                throw Error.ArgumentOutOfRange("entity"); 
            CheckModify();
            entities.Insert(index, entity);
            OnListChanged(ListChangedType.ItemAdded, index);
 
            OnAdd(entity);
        } 
 
        /// 
        /// Returns true if this entity set has a deferred query 
        /// that hasn't been executed yet.
        /// 
        public bool IsDeferred
        { 
            get { return HasSource; }
        } 
 
        /// 
        /// Returns true if values have been either assigned or loaded. 
        /// 
        internal bool HasValues {
            get { return this.source == null || this.HasAssignedValues || this.HasLoadedValues; }
        } 

        ///  
        /// Returns true if the entity set has been modified in any way by the user or its items 
        /// have been loaded from the database.
        ///  
        public bool HasLoadedOrAssignedValues {
            get { return this.HasAssignedValues || this.HasLoadedValues; }
        }
 
        /// 
        /// Returns true if the set has been modified in any way by the user. 
        ///  
        internal bool HasAssignedValues {
            get { return this.isModified; } 
        }

        /// 
        /// Returns true if the set has been loaded from the database. 
        /// 
        internal bool HasLoadedValues { 
            get { return this.isLoaded; } 
        }
 
        /// 
        /// Returns true if the set has a deferred source query that hasn't been loaded yet.
        /// 
        internal bool HasSource { 
            get { return this.source != null && !this.HasLoadedValues; }
        } 
 
        /// 
        /// Returns true if the collection has been loaded. 
        /// 
        internal bool IsLoaded {
            get {
                return this.isLoaded; 
            }
        } 
 
        internal IEnumerable Source {
            get { return this.source; } 
        }

        public void Load() {
            if (this.HasSource) { 
                ItemList addedEntities = entities;
                entities = default(ItemList); 
                foreach (TEntity e in source) entities.Add(e); 
                foreach (TEntity e in addedEntities) entities.Include(e);
                foreach (TEntity e in removedEntities) entities.Remove(e); 
                source = SourceState.Loaded;
                isLoaded = true;
                removedEntities = default(ItemList);
            } 
        }
 
        private void OnModified() { 
            isModified = true;
        } 

        [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")]
        public bool Remove(TEntity entity) {
            if (entity == null || entity == onRemoveEntity) return false; 
            CheckModify();
            int index = -1; 
            bool removed = false; 
            if (this.HasSource) {
                if (!removedEntities.Contains(entity)) { 
                    OnRemove(entity);
                    // check in entities in case it has been pre-added
                    index = entities.IndexOf(entity);
                    if (index != -1) { 
                        entities.RemoveAt(index);
                    } 
                    else { 
                        removedEntities.Add(entity);
                    } 
                    removed = true;
                }
            } else {
                index = entities.IndexOf(entity); 
                if (index != -1) {
                    OnRemove(entity); 
                    entities.RemoveAt(index); 
                    removed = true;
                } 
            }
            if (removed) {
                OnModified();
                if (this.IsLoaded) { 
                    System.Diagnostics.Debug.Assert(index != -1);
                    OnListChanged(ListChangedType.ItemDeleted, index); 
                } 
            }
            return removed; 
        }

        public void RemoveAt(int index) {
            Load(); 
            if (index < 0 || index >= Count) {
                throw Error.ArgumentOutOfRange("index"); 
            } 
            CheckModify();
            TEntity entity = entities[index]; 
            OnRemove(entity);
            entities.RemoveAt(index);
            OnModified();
            OnListChanged(ListChangedType.ItemDeleted, index); 
        }
 
        public void SetSource(IEnumerable entitySource) { 
            if (this.HasAssignedValues || this.HasLoadedValues)
                throw Error.EntitySetAlreadyLoaded(); 
            this.source = entitySource;
        }

        void CheckModify() { 
            if (onAddEntity != null || onRemoveEntity != null)
                throw Error.ModifyDuringAddOrRemove(); 
            version++; 
        }
 
        void OnAdd(TEntity entity) {
            if (onAdd != null) {
                TEntity e = onAddEntity;
                onAddEntity = entity; 
                try {
                    onAdd(entity); 
                } finally { 
                    onAddEntity = e;
                } 
            }
        }

        void OnRemove(TEntity entity) { 
            if (onRemove != null) {
                TEntity e = onRemoveEntity; 
                onRemoveEntity = entity; 
                try {
                    onRemove(entity); 
                } finally {
                    onRemoveEntity = e;
                }
            } 
        }
 
        class Enumerable : IEnumerable { 
            EntitySet entitySet;
            public Enumerable(EntitySet entitySet) { 
                this.entitySet = entitySet;
            }
            IEnumerator IEnumerable.GetEnumerator() {
                return this.GetEnumerator(); 
            }
            public IEnumerator GetEnumerator() { 
                return new Enumerator(this.entitySet); 
            }
        } 

        class Enumerator : IEnumerator {
            EntitySet entitySet;
            TEntity[] items; 
            int index;
            int endIndex; 
            int version; 

            public Enumerator(EntitySet entitySet) { 
                this.entitySet = entitySet;
                this.items = entitySet.entities.Items;
                this.index = -1;
                this.endIndex = entitySet.entities.Count - 1; 
                this.version = entitySet.version;
            } 
 
            public void Dispose() { }
 
            public bool MoveNext() {
                if (version != entitySet.version)
                    throw Error.EntitySetModifiedDuringEnumeration();
                if (index == endIndex) return false; 
                index++;
                return true; 
            } 

            public TEntity Current { 
                get { return items[index]; }
            }

            object IEnumerator.Current { 
                get { return items[index]; }
            } 
 
            void IEnumerator.Reset() {
                if (version != entitySet.version) 
                    throw Error.EntitySetModifiedDuringEnumeration();
                index = -1;
            }
        } 

        int IList.Add(object value) { 
            TEntity entity = value as TEntity; 
            if (entity == null || IndexOf(entity) >= 0) {
                throw Error.ArgumentOutOfRange("value"); 
            }
            CheckModify();
            int i = entities.Count;
            entities.Add(entity); 
            OnAdd(entity);
            return i; 
        } 

        bool IList.Contains(object value) { 
            return Contains(value as TEntity);
        }

        int IList.IndexOf(object value) { 
            return IndexOf(value as TEntity);
        } 
 
        void IList.Insert(int index, object value) {
            TEntity entity = value as TEntity; 
            if (value == null)
                throw Error.ArgumentOutOfRange("value");
            Insert(index, entity);
        } 

        bool IList.IsFixedSize { 
            get { return false; } 
        }
 
        bool IList.IsReadOnly {
            get { return false; }
        }
 
        void IList.Remove(object value) {
            Remove(value as TEntity); 
        } 

        object IList.this[int index] { 
            get {
                return this[index];
            }
            set { 
                TEntity entity = value as TEntity;
                if (value == null) throw Error.ArgumentOutOfRange("value"); 
                this[index] = entity; 
            }
        } 

        void ICollection.CopyTo(Array array, int index) {
            Load();
            if (entities.Count > 0) Array.Copy(entities.Items, 0, array, index, entities.Count); 
        }
 
        bool ICollection.IsSynchronized { 
            get { return false; }
        } 

        object ICollection.SyncRoot {
            get { return this; }
        } 

        bool ICollection.IsReadOnly { 
            get { return false; } 
        }
 
        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator();
        }
 
        void OnListChanged(ListChangedType type, int index) {
            listChanged = true; 
            if (onListChanged != null) { 
                onListChanged(this, new ListChangedEventArgs(type, index));
            } 
        }

        public event ListChangedEventHandler ListChanged {
            add { 
                onListChanged += value;
            } 
            remove { 
                onListChanged -= value;
            } 
        }

        bool IListSource.ContainsListCollection {
            get { return true; } 
        }
 
        private IBindingList cachedList = null; 

        IList IListSource.GetList() { 
            if (cachedList == null || listChanged) {
                cachedList = GetNewBindingList();
                listChanged = false;
            } 
            return cachedList;
        } 
 
        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification="Method doesn't represent a property of the type.")]
        public IBindingList GetNewBindingList() { 
            return new EntitySetBindingList(this.ToList(), this);
        }
    }
 
    struct ItemList where T : class {
        T[] items; 
        int count; 

        public int Count { 
            get { return count; }
        }

        public T[] Items { 
            get { return items; }
        } 
 
        public T this[int index] {
            get { return items[index]; } 
            set { items[index] = value; }
        }

        public void Add(T item) { 
            if (items == null || items.Length == count) GrowItems();
            items[count] = item; 
            count++; 
        }
 
        public bool Contains(T item) {
            return IndexOf(item) >= 0;
        }
 
        public Enumerator GetEnumerator() {
            Enumerator e; 
            e.items = items; 
            e.index = -1;
            e.endIndex = count - 1; 
            return e;
        }

        public bool Include(T item) { 
            if (LastIndexOf(item) >= 0) return false;
            Add(item); 
            return true; 
        }
 
        public int IndexOf(T item) {
            for (int i = 0; i < count; i++) {
                if (items[i] == item) return i;
            } 
            return -1;
        } 
 
        public void Insert(int index, T item) {
            if (items == null || items.Length == count) GrowItems(); 
            if (index < count) Array.Copy(items, index, items, index + 1, count - index);
            items[index] = item;
            count++;
        } 

        public int LastIndexOf(T item) { 
            int i = count; 
            while (i > 0) {
                --i; 
                if (items[i] == item) return i;
            }
            return -1;
        } 

        public bool Remove(T item) { 
            int i = IndexOf(item); 
            if (i < 0) return false;
            RemoveAt(i); 
            return true;
        }

        public void RemoveAt(int index) { 
            count--;
            if (index < count) Array.Copy(items, index + 1, items, index, count - index); 
            items[count] = default(T); 
        }
 
        void GrowItems() {
            Array.Resize(ref items, count == 0 ? 4 : count * 2);
        }
 
        public struct Enumerator {
            internal T[] items; 
            internal int index; 
            internal int endIndex;
 
            public bool MoveNext() {
                if (index == endIndex) return false;
                index++;
                return true; 
            }
 
            public T Current { 
                get { return items[index]; }
            } 
        }
    }

    [SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces", Justification = "[....]: The name clearly describes function and the namespace is under a DLinq namespace which will make the distinction clear.")] 
    [DataContract]
    [Serializable] 
    public sealed class Binary : IEquatable { 
        [DataMember(Name="Bytes")]
        byte[] bytes; 
        int? hashCode;

        public Binary(byte[] value) {
            if (value == null) 
                throw Error.ArgumentNull("value");
            this.bytes = new byte[value.Length]; 
            Array.Copy(value, this.bytes, value.Length); 
            this.ComputeHash();
        } 

        public byte[] ToArray() {
            byte[] copy = new byte[this.bytes.Length];
            Array.Copy(this.bytes, copy, copy.Length); 
            return copy;
        } 
 
        public int Length {
            get { return this.bytes.Length; } 
        }

        public static implicit operator Binary(byte[] value) {
            return new Binary(value); 
        }
 
        public bool Equals(Binary other) { 
            return this.EqualsTo(other);
        } 

        public static bool operator ==(Binary binary1, Binary binary2) {
            if ((object)binary1 == (object)binary2)
                return true; 
            if ((object)binary1 == null && (object)binary2 == null)
                return true; 
            if ((object)binary1 == null || (object)binary2 == null) 
                return false;
            return binary1.EqualsTo(binary2); 
        }

        public static bool operator !=(Binary binary1, Binary binary2) {
            if ((object)binary1 == (object)binary2) 
                return false;
            if ((object)binary1 == null && (object)binary2 == null) 
                return false; 
            if ((object)binary1 == null || (object)binary2 == null)
                return true; 
            return !binary1.EqualsTo(binary2);
        }

        public override bool Equals(object obj) { 
            return this.EqualsTo(obj as Binary);
        } 
 
        public override int GetHashCode() {
            if (!hashCode.HasValue) { 
                // hash code is not marked [DataMember], so when
                // using the DataContractSerializer, we'll need
                // to recompute the hash after deserialization.
                ComputeHash(); 
            }
            return this.hashCode.Value; 
        } 

        public override string ToString() { 
            StringBuilder sb = new StringBuilder();
            sb.Append("\"");
            sb.Append(System.Convert.ToBase64String(this.bytes, 0, this.bytes.Length));
            sb.Append("\""); 
            return sb.ToString();
        } 
 
        private bool EqualsTo(Binary binary) {
            if ((object)this == (object)binary) 
                return true;
            if ((object)binary == null)
                return false;
            if (this.bytes.Length != binary.bytes.Length) 
                return false;
            if (this.hashCode != binary.hashCode) 
                return false; 
            for (int i = 0, n = this.bytes.Length; i < n; i++) {
                if (this.bytes[i] != binary.bytes[i]) 
                    return false;
            }
            return true;
        } 

        ///  
        /// Simple hash using pseudo-random coefficients for each byte in 
        /// the array to achieve order dependency.
        ///  
        private void ComputeHash() {
            int s = 314, t = 159;
            hashCode = 0;
            for (int i = 0; i < bytes.Length; i++) { 
                hashCode = hashCode * s + bytes[i];
                s = s * t; 
            } 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK