Example #1
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. Only case sensitive
        /// setter is supported in ExpandoObject.
        /// </summary>
        internal int TrySetValue(ExpandoClass klass, int index, object value, bool caseInsensitive) {
            Debug.Assert(index >= 0);

            lock (LockObject) {
                ExpandoData data = _data;

                if (data.Class != klass || caseInsensitive) {
                    //the class has changed or we are doing a case-insensitive search, 
                    //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, this);
                    if (index == ExpandoObject.AmbiguousMatchFound) {
                        return index;
                    }
                    if (index == ExpandoObject.NoMatch) {
                        //Before creating a new class with the new member, need to check 
                        //if there is the exact same member but is deleted. We should reuse
                        //the class if there is such a member.
                        int exactMatch = caseInsensitive ? 
                            data.Class.GetValueIndexCaseSensitive(name) :
                            index;
                        if (exactMatch != ExpandoObject.NoMatch) {
                            Debug.Assert(data.Data[exactMatch] == Uninitialized);
                            index = exactMatch;
                        } else {
                            ExpandoClass newClass = data.Class.FindNewClass(name);
                            data = PromoteClassWorker(data.Class, newClass);
                            //After the class promotion, there must be an exact match,
                            //so we can do case-sensitive search here.
                            index = data.Class.GetValueIndexCaseSensitive(name);

                            Debug.Assert(index != ExpandoObject.NoMatch);
                        }
                    }
                }

                data.Data[index] = value;
                return index;
            }           
        }              
Example #2
0
        /// <summary>
        /// Deletes the data stored for the specified class at the specified index.
        /// </summary>
        internal int TryDeleteValue(ExpandoClass klass, int index, bool caseInsensitive) {
            if (index == ExpandoObject.NoMatch) {
                return index;
            }

            lock (LockObject) {
                ExpandoData data = _data;

                if (data.Class != klass || caseInsensitive) {
                    // the class has changed or we are doing a case-insensitive search,
                    // 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, this);
                    if (index < 0) {
                        return index;
                    }
                }

                object oldValue = data.Data[index];
                data.Data[index] = Uninitialized;
                return oldValue == Uninitialized ? ExpandoObject.NoMatch : index;
            }
        }