12 [global::__DynamicallyInvokable]
15 private sealed
class KeyCollectionDebugView
24 string[] array =
new string[collection.Count];
25 collection.CopyTo(array, 0);
32 this.collection = collection;
36 [DebuggerTypeProxy(typeof(KeyCollectionDebugView))]
37 [DebuggerDisplay(
"Count = {Count}")]
42 private readonly
int _expandoVersion;
44 private readonly
int _expandoCount;
46 private readonly ExpandoData _expandoData;
57 public bool IsReadOnly =>
true;
61 lock (expando.LockObject)
64 _expandoVersion = expando._data.Version;
65 _expandoCount = expando._count;
66 _expandoData = expando._data;
70 private void CheckVersion()
72 if (_expando._data.Version != _expandoVersion || _expandoData != _expando._data)
74 throw Error.CollectionModifiedWhileEnumerating();
78 public void Add(
string item)
80 throw Error.CollectionReadOnly();
85 throw Error.CollectionReadOnly();
88 public bool Contains(
string item)
90 lock (_expando.LockObject)
93 return _expando.ExpandoContainsKey(item);
97 public void CopyTo(
string[] array,
int arrayIndex)
99 ContractUtils.RequiresNotNull(array,
"array");
100 ContractUtils.RequiresArrayRange(array, arrayIndex, _expandoCount,
"arrayIndex",
"Count");
101 lock (_expando.LockObject)
104 ExpandoData data = _expando._data;
105 for (
int i = 0; i < data.Class.Keys.Length; i++)
107 if (data[i] != Uninitialized)
109 array[arrayIndex++] = data.Class.Keys[i];
115 public bool Remove(
string item)
117 throw Error.CollectionReadOnly();
123 for (
int i = _expandoData.Class.Keys.Length; j < i; j++)
126 if (_expandoData[j] != Uninitialized)
128 yield
return _expandoData.Class.Keys[j];
135 return GetEnumerator();
139 private sealed
class ValueCollectionDebugView
144 public object[] Items
148 object[] array =
new object[collection.Count];
149 collection.CopyTo(array, 0);
156 this.collection = collection;
160 [DebuggerTypeProxy(typeof(ValueCollectionDebugView))]
161 [DebuggerDisplay(
"Count = {Count}")]
166 private readonly
int _expandoVersion;
168 private readonly
int _expandoCount;
170 private readonly ExpandoData _expandoData;
177 return _expandoCount;
181 public bool IsReadOnly =>
true;
185 lock (expando.LockObject)
188 _expandoVersion = expando._data.Version;
189 _expandoCount = expando._count;
190 _expandoData = expando._data;
194 private void CheckVersion()
196 if (_expando._data.Version != _expandoVersion || _expandoData != _expando._data)
198 throw Error.CollectionModifiedWhileEnumerating();
202 public void Add(
object item)
204 throw Error.CollectionReadOnly();
209 throw Error.CollectionReadOnly();
212 public bool Contains(
object item)
214 lock (_expando.LockObject)
217 ExpandoData data = _expando._data;
218 for (
int i = 0; i < data.Class.Keys.Length; i++)
220 if (
object.Equals(data[i], item))
229 public void CopyTo(
object[] array,
int arrayIndex)
231 ContractUtils.RequiresNotNull(array,
"array");
232 ContractUtils.RequiresArrayRange(array, arrayIndex, _expandoCount,
"arrayIndex",
"Count");
233 lock (_expando.LockObject)
236 ExpandoData data = _expando._data;
237 for (
int i = 0; i < data.Class.Keys.Length; i++)
239 if (data[i] != Uninitialized)
241 array[arrayIndex++] = data[i];
247 public bool Remove(
object item)
249 throw Error.CollectionReadOnly();
254 ExpandoData data = _expando._data;
255 for (
int i = 0; i < data.Class.Keys.Length; i++)
258 object obj = data[i];
259 if (obj != Uninitialized)
268 return GetEnumerator();
283 ExpandoClass
@class = Value.Class;
284 int valueIndex =
@class.GetValueIndex(name, ignoreCase, Value);
288 if (fallbackInvoke !=
null)
290 dynamicMetaObject = fallbackInvoke(dynamicMetaObject);
296 return AddDynamicTestAndDefer(binder, Value.Class,
null, dynamicMetaObject);
301 ContractUtils.RequiresNotNull(binder,
"binder");
307 ContractUtils.RequiresNotNull(binder,
"binder");
313 ContractUtils.RequiresNotNull(binder,
"binder");
314 ContractUtils.RequiresNotNull(value,
"value");
317 ExpandoClass classEnsureIndex = GetClassEnsureIndex(binder.
Name, binder.
IgnoreCase, Value, out klass, out index);
318 return AddDynamicTestAndDefer(binder, klass, classEnsureIndex,
new DynamicMetaObject(
Expression.Call(typeof(
RuntimeOps).GetMethod(
"ExpandoTrySetValue"), GetLimitedSelf(),
Expression.Constant(klass, typeof(
object)),
Expression.Constant(index),
Expression.Convert(value.Expression, typeof(
object)),
Expression.Constant(binder.
Name),
Expression.Constant(binder.
IgnoreCase)),
BindingRestrictions.
Empty));
323 ContractUtils.RequiresNotNull(binder,
"binder");
324 int valueIndex = Value.Class.GetValueIndex(binder.
Name, binder.
IgnoreCase, Value);
328 return AddDynamicTestAndDefer(binder, Value.Class,
null, succeeds);
333 ExpandoData expandoData = Value._data;
334 ExpandoClass klass = expandoData.Class;
335 for (
int i = 0; i < klass.Keys.Length; i++)
337 object obj = expandoData[i];
338 if (obj != Uninitialized)
340 yield
return klass.Keys[i];
348 if (originalClass !=
null)
355 private ExpandoClass GetClassEnsureIndex(
string name,
bool caseInsensitive,
ExpandoObject obj, out ExpandoClass klass, out
int index)
357 ExpandoClass
@class = Value.Class;
358 index =
@class.GetValueIndex(name, caseInsensitive, obj);
366 index = (klass =
@class.FindNewClass(name)).GetValueIndexCaseSensitive(name);
375 if (TypeUtils.AreEquivalent(base.Expression.Type, base.LimitType))
377 return base.Expression;
379 return Expression.Convert(base.Expression, base.LimitType);
388 private class ExpandoData
390 internal static ExpandoData Empty =
new ExpandoData();
392 internal readonly ExpandoClass
Class;
394 private readonly
object[] _dataArray;
396 private int _version;
398 internal object this[
int index]
402 return _dataArray[index];
407 _dataArray[index] = value;
411 internal int Version => _version;
413 internal int Length => _dataArray.Length;
415 private ExpandoData()
417 Class = ExpandoClass.Empty;
418 _dataArray =
new object[0];
421 internal ExpandoData(ExpandoClass klass,
object[] data,
int version)
428 internal ExpandoData UpdateClass(ExpandoClass newClass)
430 if (_dataArray.Length >= newClass.Keys.Length)
432 this[newClass.Keys.Length - 1] = Uninitialized;
433 return new ExpandoData(newClass, _dataArray, _version);
435 int index = _dataArray.Length;
436 object[] array =
new object[GetAlignedSize(newClass.Keys.Length)];
437 Array.
Copy(_dataArray, array, _dataArray.Length);
438 ExpandoData expandoData =
new ExpandoData(newClass, array, _version);
439 expandoData[index] = Uninitialized;
443 private static int GetAlignedSize(
int len)
445 return (len + 7) & -8;
449 internal readonly
object LockObject;
451 private ExpandoData _data;
455 internal static readonly
object Uninitialized =
new object();
457 internal const int AmbiguousMatchFound = -2;
459 internal const int NoMatch = -1;
463 internal ExpandoClass Class => _data.Class;
465 [global::__DynamicallyInvokable]
468 [global::__DynamicallyInvokable]
471 return new KeyCollection(
this);
475 [global::__DynamicallyInvokable]
478 [global::__DynamicallyInvokable]
481 return new ValueCollection(
this);
485 [global::__DynamicallyInvokable]
488 [global::__DynamicallyInvokable]
491 if (!TryGetValueForKey(key, out
object value))
493 throw Error.KeyDoesNotExistInExpando(key);
497 [global::__DynamicallyInvokable]
500 ContractUtils.RequiresNotNull(key,
"key");
501 TrySetValue(
null, -1, value, key, ignoreCase:
false, add:
false);
505 [global::__DynamicallyInvokable]
508 [global::__DynamicallyInvokable]
515 [global::__DynamicallyInvokable]
518 [global::__DynamicallyInvokable]
526 [global::__DynamicallyInvokable]
529 [global::__DynamicallyInvokable]
534 [global::__DynamicallyInvokable]
542 [global::__DynamicallyInvokable]
545 _data = ExpandoData.Empty;
546 LockObject =
new object();
549 internal bool TryGetValue(
object indexClass,
int index,
string name,
bool ignoreCase, out
object value)
551 ExpandoData data = _data;
552 if ((data.Class != indexClass) | ignoreCase)
554 index = data.Class.GetValueIndex(name, ignoreCase,
this);
557 throw Error.AmbiguousMatchInExpandoObject(name);
565 object obj = data[index];
566 if (obj == Uninitialized)
575 internal void TrySetValue(
object indexClass,
int index,
object value,
string name,
bool ignoreCase,
bool add)
577 ExpandoData expandoData;
582 if ((expandoData.Class != indexClass) | ignoreCase)
584 index = expandoData.Class.GetValueIndex(name, ignoreCase,
this);
588 throw Error.AmbiguousMatchInExpandoObject(name);
591 int num = ignoreCase ? expandoData.Class.GetValueIndexCaseSensitive(name) : index;
598 ExpandoClass newClass = expandoData.Class.FindNewClass(name);
599 expandoData = PromoteClassCore(expandoData.Class, newClass);
600 index = expandoData.Class.GetValueIndexCaseSensitive(name);
606 obj = expandoData[index];
607 if (obj == Uninitialized)
613 throw Error.SameKeyExistsInExpando(name);
615 expandoData[index] = value;
618 if (propertyChanged !=
null && value != obj)
624 internal bool TryDeleteValue(
object indexClass,
int index,
string name,
bool ignoreCase,
object deleteValue)
630 if ((data.Class != indexClass) | ignoreCase)
632 index = data.Class.GetValueIndex(name, ignoreCase,
this);
635 throw Error.AmbiguousMatchInExpandoObject(name);
642 object obj = data[index];
643 if (obj == Uninitialized)
647 if (deleteValue != Uninitialized && !
object.Equals(obj, deleteValue))
651 data[index] = Uninitialized;
658 internal bool IsDeletedMember(
int index)
660 if (index == _data.Length)
664 return _data[index] == Uninitialized;
667 private ExpandoData PromoteClassCore(ExpandoClass oldClass, ExpandoClass newClass)
671 if (_data.Class == oldClass)
673 _data = _data.UpdateClass(newClass);
679 internal void PromoteClass(
object oldClass,
object newClass)
681 PromoteClassCore((ExpandoClass)oldClass, (ExpandoClass)newClass);
687 [global::__DynamicallyInvokable]
688 DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(
Expression parameter)
690 return new MetaExpando(parameter,
this);
693 private void TryAddMember(
string key,
object value)
695 ContractUtils.RequiresNotNull(key,
"key");
696 TrySetValue(
null, -1, value, key, ignoreCase:
false, add:
true);
699 private bool TryGetValueForKey(
string key, out
object value)
701 return TryGetValue(
null, -1, key, ignoreCase:
false, out value);
704 private bool ExpandoContainsKey(
string key)
706 return _data.Class.GetValueIndexCaseSensitive(key) >= 0;
709 [global::__DynamicallyInvokable]
712 TryAddMember(key, value);
715 [global::__DynamicallyInvokable]
718 ContractUtils.RequiresNotNull(key,
"key");
719 ExpandoData data = _data;
720 int valueIndexCaseSensitive = data.Class.GetValueIndexCaseSensitive(key);
721 if (valueIndexCaseSensitive >= 0)
723 return data[valueIndexCaseSensitive] != Uninitialized;
728 [global::__DynamicallyInvokable]
731 ContractUtils.RequiresNotNull(key,
"key");
732 return TryDeleteValue(
null, -1, key, ignoreCase:
false, Uninitialized);
735 [global::__DynamicallyInvokable]
738 return TryGetValueForKey(key, out value);
741 [global::__DynamicallyInvokable]
744 TryAddMember(item.Key, item.Value);
747 [global::__DynamicallyInvokable]
754 _data = ExpandoData.Empty;
758 if (propertyChanged ==
null)
763 for (
int num = data.Class.Keys.Length; i < num; i++)
765 if (data[i] != Uninitialized)
772 [global::__DynamicallyInvokable]
775 if (!TryGetValueForKey(item.Key, out
object value))
779 return object.Equals(value, item.Value);
782 [global::__DynamicallyInvokable]
785 ContractUtils.RequiresNotNull(array,
"array");
786 ContractUtils.RequiresArrayRange(array, arrayIndex, _count,
"arrayIndex",
"Count");
791 array[arrayIndex++] = item;
796 [global::__DynamicallyInvokable]
799 return TryDeleteValue(
null, -1, item.Key, ignoreCase:
false, item.Value);
802 [global::__DynamicallyInvokable]
805 ExpandoData data = _data;
806 return GetExpandoEnumerator(data, data.Version);
811 [global::__DynamicallyInvokable]
814 ExpandoData data = _data;
815 return GetExpandoEnumerator(data, data.Version);
823 if (i < data.Class.Keys.Length)
825 if (_data.Version != version || data != _data)
829 object obj = data[i];
830 if (obj != Uninitialized)
839 throw Error.CollectionModifiedWhileEnumerating();
Notifies clients that a property value has changed.
abstract DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
When overridden in the derived class, performs the binding of the dynamic invoke operation if the tar...
bool IgnoreCase
Gets the value indicating if the string comparison should ignore the case of the member name.
bool IgnoreCase
Gets the value indicating if the string comparison should ignore the case of the member name.
ExpandoObject()
Initializes a new ExpandoObject that does not have members.
string Name
Gets the name of the member to delete.
Provides data for the E:System.ComponentModel.INotifyPropertyChanged.PropertyChanged event.
Represents the dynamic get member operation at the call site, providing the binding semantic and the ...
Represents the dynamic set member operation at the call site, providing the binding semantic and the ...
static BindingRestrictions GetTypeRestriction(Expression expression, Type type)
Creates the binding restriction that check the expression for runtime type identity.
DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args)
Performs the binding of the dynamic invoke member operation if the target dynamic object cannot bind.
static readonly BindingRestrictions Empty
Represents an empty set of binding restrictions. This field is read only.
static Delegate Remove(Delegate source, Delegate value)
Removes the last occurrence of the invocation list of a delegate from the invocation list of another ...
static Delegate Combine(Delegate a, Delegate b)
Concatenates the invocation lists of two delegates.
BindingRestrictions Merge(BindingRestrictions restrictions)
Merges the set of binding restrictions with the current binding restrictions.
PropertyChangedEventHandler PropertyChanged
Occurs when a property value changes.
DynamicMetaObject FallbackGetMember(DynamicMetaObject target)
Performs the binding of the dynamic get member operation if the target dynamic object cannot bind.
DynamicMetaObject FallbackDeleteMember(DynamicMetaObject target)
Performs the binding of the dynamic delete member operation if the target dynamic object cannot bind.
Defines a key/value pair that can be set or retrieved.
Exposes an enumerator, which supports a simple iteration over a non-generic collection....
delegate void PropertyChangedEventHandler(object sender, PropertyChangedEventArgs e)
Represents the method that will handle the E:System.ComponentModel.INotifyPropertyChanged....
Provides the base class from which the classes that represent expression tree nodes are derived....
string Name
Gets the name of the member to invoke.
void Add(object key, object value)
Adds an element with the provided key and value to the T:System.Collections.IDictionary object.
Represents the invoke member dynamic operation at the call site, providing the binding semantic and t...
string Name
Gets the name of the member to obtain.
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Represents a delegate, which is a data structure that refers to a static method or to a class instanc...
void Remove(object key)
Removes the element with the specified key from the T:System.Collections.IDictionary object.
Represents the version number of an assembly, operating system, or the common language runtime....
The Add key (the addition key on the numeric keypad).
Represents a named parameter expression.
IEnumerator GetEnumerator()
Returns an enumerator that iterates through a collection.
Represents a set of binding restrictions on the T:System.Dynamic.DynamicMetaObject under which the dy...
Attribute can be applied to a class.
ICollection Keys
Gets an T:System.Collections.ICollection object containing the keys of the T:System....
ICollection Values
Gets an T:System.Collections.ICollection object containing the values in the T:System....
static void Copy(Array sourceArray, Array destinationArray, int length)
Copies a range of elements from an T:System.Array starting at the first element and pastes them into ...
bool IgnoreCase
Gets the value indicating if the string comparison should ignore the case of the member name.
int Count
Gets the number of elements contained in the T:System.Collections.ICollection.
Defines size, enumerators, and synchronization methods for all nongeneric collections.
void CopyTo(Array array, int index)
Copies the elements of the T:System.Collections.ICollection to an T:System.Array, starting at a parti...
Represents an object whose members can be dynamically added and removed at run time.
DebuggerBrowsableState
Provides display instructions for the debugger.
bool IgnoreCase
Gets the value indicating if the string comparison should ignore the case of the member name.
Represents a nongeneric collection of key/value pairs.
string Name
Gets the name of the member to obtain.
Represents the dynamic delete member operation at the call site, providing the binding semantic and t...
Contains helper methods called from dynamically generated methods.