internal ValueCollection(ExpandoObject expando) { lock (expando.LockObject) { _expando = expando; _expandoVersion = expando._data.Version; _expandoCount = expando._count; _expandoData = expando._data; } }
/// <summary> /// Promotes the class from the old type to the new type and returns the new /// ExpandoData object. /// </summary> private ExpandoData PromoteClassCore(ExpandoClass oldClass, ExpandoClass newClass) { Debug.Assert(oldClass != newClass); ContractUtils.AssertLockHeld(LockObject); if (_data.Class == oldClass) { _data = _data.UpdateClass(newClass); } return(_data); }
/// <summary> /// Promotes the class from the old type to the new type and returns the new /// ExpandoData object. /// </summary> private ExpandoData PromoteClassCore(ExpandoClass oldClass, ExpandoClass newClass) { Debug.Assert(oldClass != newClass); lock (LockObject) { if (_data.Class == oldClass) { _data = _data.UpdateClass(newClass); } return(_data); } }
/// <summary> /// Promotes the class from the old type to the new type and returns the new /// ExpandoData object. /// </summary> private ExpandoData PromoteClassWorker(ExpandoClass oldClass, ExpandoClass newClass) { Debug.Assert(oldClass != newClass); lock (this) { if (_data.Class == oldClass) { _data = new ExpandoData(newClass, newClass.GetNewKeys(_data.Data)); } return(_data); } }
public void CopyTo(object[] array, int arrayIndex) { ContractUtils.RequiresNotNull(array, "array"); ContractUtils.RequiresArrayRange(array, arrayIndex, _expandoCount, "arrayIndex", "Count"); lock (_expando.LockObject) { CheckVersion(); ExpandoData data = _expando._data; for (int i = 0; i < data.Class.Keys.Length; i++) { if (data[i] != Uninitialized) { array[arrayIndex++] = data[i]; } } } }
public IEnumerator <object> GetEnumerator() { ExpandoData data = _expando._data; for (int i = 0; i < data.Class.Keys.Length; i++) { CheckVersion(); // Capture the value into a temp so we don't inadvertently // return Uninitialized. object temp = data[i]; if (temp != Uninitialized) { yield return(temp); } } }
public void CopyTo(object?[] array, int arrayIndex) { ArgumentNullException.ThrowIfNull(array); ContractUtils.RequiresArrayRange(array, arrayIndex, _expandoCount, nameof(arrayIndex), nameof(Count)); lock (_expando.LockObject) { CheckVersion(); ExpandoData data = _expando._data; for (int i = 0; i < data.Class.Keys.Length; i++) { if (data[i] != Uninitialized) { array[arrayIndex++] = data[i]; } } } }
/// <summary> /// Try to get 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 TryGetValue(object indexClass, int index, string name, bool ignoreCase, out object value) { // 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; if (data.Class != indexClass || ignoreCase) { /* Re-search for the index matching the name here if * 1) the class has changed, we need to get the correct index and return * the value there. * 2) the search is case insensitive: * a. the member specified by index may be deleted, but there might be other * members matching the name if the binder is case insensitive. * b. the member that exactly matches the name didn't exist before and exists now, * need to find the exact match. */ index = data.Class.GetValueIndex(name, ignoreCase, this); if (index == ExpandoObject.AmbiguousMatchFound) { throw System.Linq.Expressions.Error.AmbiguousMatchInExpandoObject(name); } } if (index == ExpandoObject.NoMatch) { value = null; return(false); } // Capture the value into a temp, so it doesn't get mutated after we check // for Uninitialized. object temp = data[index]; if (temp == Uninitialized) { value = null; return(false); } // index is now known to be correct value = temp; return(true); }
public bool Contains(object item) { lock (_expando.LockObject) { CheckVersion(); ExpandoData data = _expando._data; for (int i = 0; i < data.Class.Keys.Length; i++) { // See comment in TryDeleteValue; it's okay to call // object.Equals with the lock held. if (object.Equals(data[i], item)) { return(true); } } return(false); } }
/// <summary> /// Update the associated class and increases the storage for the data array if needed. /// </summary> internal ExpandoData UpdateClass(ExpandoClass newClass) { if (_dataArray.Length >= newClass.Keys.Length) { // we have extra space in our buffer, just initialize it to Uninitialized. this[newClass.Keys.Length - 1] = ExpandoObject.Uninitialized; return(new ExpandoData(newClass, _dataArray, _version)); } else { // we've grown too much - we need a new object array int oldLength = _dataArray.Length; object[] arr = new object[GetAlignedSize(newClass.Keys.Length)]; Array.Copy(_dataArray, 0, arr, 0, _dataArray.Length); ExpandoData newData = new ExpandoData(newClass, arr, _version); newData[oldLength] = ExpandoObject.Uninitialized; return(newData); } }
// Note: takes the data and version as parameters so they will be // captured before the first call to MoveNext(). private IEnumerator <KeyValuePair <string, object> > GetExpandoEnumerator(ExpandoData data, int version) { for (int i = 0; i < data.Class.Keys.Length; i++) { if (_data.Version != version || data != _data) { // The underlying expando object has changed: // 1) the version of the expando data changed // 2) the data object is changed throw System.Linq.Expressions.Error.CollectionModifiedWhileEnumerating(); } // Capture the value into a temp so we don't inadvertently // return Uninitialized. object temp = data[i]; if (temp != Uninitialized) { yield return(new KeyValuePair <string, object>(data.Class.Keys[i], temp)); } } }
void ICollection <KeyValuePair <string, object> > .Clear() { // We remove both class and data! ExpandoData data; lock (LockObject) { data = _data; _data = ExpandoData.Empty; _count = 0; } // Notify property changed for all properties. for (int i = 0, n = data.Class.Keys.Length; i < n; i++) { if (data[i] != Uninitialized) { _propertyChanged.Invoke(this, new PropertyChangedEventArgs(data.Class.Keys[i])); } } }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { ExpandoData data = _data; return(GetExpandoEnumerator(data, data.Version)); }
IEnumerator <KeyValuePair <string, object> > IEnumerable <KeyValuePair <string, object> > .GetEnumerator() { ExpandoData data = _data; return(GetExpandoEnumerator(data, data.Version)); }
/// <summary> /// Creates a new ExpandoObject with no members. /// </summary> public ExpandoObject() { _data = ExpandoData.Empty; LockObject = new object(); }
// the count of available members // A marker object used to identify that a value is uninitialized. // The value is used to indicate there is no matching member /// <summary> /// Creates a new ExpandoObject with no members. /// </summary> public ExpandoObject() { _data = ExpandoData.Empty; _propertyChanged = new StrongEvent <PropertyChangedEventArgs>(true); LockObject = new object(); }
internal static object Uninitialized = new object(); // A marker object used to identify that a value is uninitialized. /// <summary> /// Creates a new Expando object with no members. /// </summary> public ExpandoObject() { _data = ExpandoData.Empty; }
/// <summary> /// Promotes the class from the old type to the new type and returns the new /// ExpandoData object. /// </summary> private ExpandoData PromoteClassWorker(ExpandoClass oldClass, ExpandoClass newClass) { Debug.Assert(oldClass != newClass); lock (this) { if (_data.Class == oldClass) { _data = new ExpandoData(newClass, newClass.GetNewKeys(_data.Data)); } return _data; } }
IEnumerator IEnumerable.GetEnumerator() { ExpandoData data = _data; return(GetExpandoEnumerator(data, data.Version)); }
internal const int NoMatch = -1; // The value is used to indicate there is no matching member /// <summary> /// Creates a new ExpandoObject with no members. /// </summary> public ExpandoObject() { _data = ExpandoData.Empty; LockObject = new object(); }