/// <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); }
/// <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; } }
/// <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); } }
/// <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; }
/// <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; } }