Example #1
0
        /// <summary>
        /// Gets the data stored for the specified class at the specified index.  If the
        /// class has changed a full lookup for the slot will be performed and the correct
        /// value will be retrieved.
        /// </summary>
        internal object GetValue(ExpandoClass klass, int index, bool caseInsensitive)
        {
            Debug.Assert(index != -1);

            // read the data now.  The data is immutable so we get a consistent view.
            // If there's a concurrent writer they will replace data and it just appears
            // that we won the race
            ExpandoData data = _data;
            object      res  = Uninitialized;

            if (data.Class != klass)
            {
                // the class has changed, we need to get the correct index and return
                // the value there.
                index = data.Class.GetValueIndex(klass.GetIndexName(index), caseInsensitive);
            }

            // index is now known to be correct
            res = data.Data[index];

            if (res == Uninitialized)
            {
                throw new MissingMemberException(klass.GetIndexName(index));
            }

            return(res);
        }
Example #2
0
        /// <summary>
        /// Sets the data for the specified class at the specified index.  If the class has
        /// changed then a full look for the slot will be performed.  If the new class does
        /// not have the provided slot then the Expando's class will change.
        /// </summary>
        internal void SetValue(ExpandoClass klass, int index, bool caseInsensitive, object value)
        {
            Debug.Assert(index != -1);

            lock (this) {
                ExpandoData data = _data;

                if (data.Class != klass)
                {
                    // the class has changed, we need to get the correct index and set
                    // the value there.  If we don't have the value then we need to
                    // promote the class - that should only happen when we have multiple
                    // concurrent writers.
                    string name = klass.GetIndexName(index);
                    index = data.Class.GetValueIndex(name, caseInsensitive);
                    if (index == -1)
                    {
                        ExpandoClass newClass = data.Class.FindNewClass(name, caseInsensitive);

                        data  = PromoteClassWorker(data.Class, newClass);
                        index = data.Class.GetValueIndex(name, caseInsensitive);

                        Debug.Assert(index != -1);
                    }
                }

                data.Data[index] = value;
            }
        }
Example #3
0
        /// <summary>
        /// Gets the data stored for the specified class at the specified index.  If the
        /// class has changed a full lookup for the slot will be performed and the correct
        /// value will be retrieved.
        /// </summary>
        internal bool DeleteValue(ExpandoClass klass, int index, bool caseInsensitive)
        {
            Debug.Assert(index != -1);

            lock (this) {
                ExpandoData data = _data;

                if (data.Class != klass)
                {
                    // the class has changed, we need to get the correct index.  If there is
                    // no associated index we simply can't have the value and we return
                    // false.
                    index = data.Class.GetValueIndex(klass.GetIndexName(index), caseInsensitive);
                    if (index == -1)
                    {
                        return(false);
                    }
                }

                object curValue = data.Data[index];
                data.Data[index] = Uninitialized;

                return(curValue != Uninitialized);
            }
        }
Example #4
0
        /// <summary>
        /// Gets the data stored for the specified class at the specified index.  If the
        /// class has changed a full lookup for the slot will be performed and the correct
        /// value will be retrieved.
        /// </summary>
        internal object GetValue(ExpandoClass klass, int index, bool caseInsensitive) {
            Debug.Assert(index != -1);

            // read the data now.  The data is immutable so we get a consistent view.
            // If there's a concurrent writer they will replace data and it just appears
            // that we won the race
            ExpandoData data = _data;
            object res = Uninitialized;
            if (data.Class != klass) {
                // the class has changed, we need to get the correct index and return
                // the value there.
                index = data.Class.GetValueIndex(klass.GetIndexName(index), caseInsensitive);
            }

            // index is now known to be correct
            res = data.Data[index];

            if (res == Uninitialized) {
                throw new MissingMemberException(klass.GetIndexName(index));
            }

            return res;
        }
Example #5
0
        /// <summary>
        /// Sets the data for the specified class at the specified index.  If the class has
        /// changed then a full look for the slot will be performed.  If the new class does
        /// not have the provided slot then the Expando's class will change.
        /// </summary>
        internal void SetValue(ExpandoClass klass, int index, bool caseInsensitive, object value) {
            Debug.Assert(index != -1);

            lock (this) {
                ExpandoData data = _data;

                if (data.Class != klass) {
                    // the class has changed, we need to get the correct index and set
                    // the value there.  If we don't have the value then we need to
                    // promote the class - that should only happen when we have multiple
                    // concurrent writers.
                    string name = klass.GetIndexName(index);
                    index = data.Class.GetValueIndex(name, caseInsensitive);
                    if (index == -1) {
                        ExpandoClass newClass = data.Class.FindNewClass(name, caseInsensitive);

                        data = PromoteClassWorker(data.Class, newClass);
                        index = data.Class.GetValueIndex(name, caseInsensitive);

                        Debug.Assert(index != -1);
                    }
                }

                data.Data[index] = value;
            }           
        }              
Example #6
0
        /// <summary>
        /// Gets the data stored for the specified class at the specified index.  If the
        /// class has changed a full lookup for the slot will be performed and the correct
        /// value will be retrieved.
        /// </summary>
        internal bool DeleteValue(ExpandoClass klass, int index, bool caseInsensitive) {
            Debug.Assert(index != -1);

            lock (this) {
                ExpandoData data = _data;

                if (data.Class != klass) {
                    // the class has changed, we need to get the correct index.  If there is
                    // no associated index we simply can't have the value and we return
                    // false.
                    index = data.Class.GetValueIndex(klass.GetIndexName(index), caseInsensitive);
                    if (index == -1) {
                        return false;
                    }
                }

                object curValue = data.Data[index];
                data.Data[index] = Uninitialized;

                return curValue != Uninitialized;
            }
        }