mscorlib(4.0.0.0) API with additions
ExpandoObject.cs
1 using System.Collections;
4 using System.Diagnostics;
5 using System.Dynamic.Utils;
8 
9 namespace System.Dynamic
10 {
12  [global::__DynamicallyInvokable]
13  public sealed class ExpandoObject : IDynamicMetaObjectProvider, IDictionary<string, object>, ICollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable, INotifyPropertyChanged
14  {
15  private sealed class KeyCollectionDebugView
16  {
17  private ICollection<string> collection;
18 
19  [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
20  public string[] Items
21  {
22  get
23  {
24  string[] array = new string[collection.Count];
25  collection.CopyTo(array, 0);
26  return array;
27  }
28  }
29 
30  public KeyCollectionDebugView(ICollection<string> collection)
31  {
32  this.collection = collection;
33  }
34  }
35 
36  [DebuggerTypeProxy(typeof(KeyCollectionDebugView))]
37  [DebuggerDisplay("Count = {Count}")]
38  private class KeyCollection : ICollection<string>, IEnumerable<string>, IEnumerable
39  {
40  private readonly ExpandoObject _expando;
41 
42  private readonly int _expandoVersion;
43 
44  private readonly int _expandoCount;
45 
46  private readonly ExpandoData _expandoData;
47 
48  public int Count
49  {
50  get
51  {
52  CheckVersion();
53  return _expandoCount;
54  }
55  }
56 
57  public bool IsReadOnly => true;
58 
59  internal KeyCollection(ExpandoObject expando)
60  {
61  lock (expando.LockObject)
62  {
63  _expando = expando;
64  _expandoVersion = expando._data.Version;
65  _expandoCount = expando._count;
66  _expandoData = expando._data;
67  }
68  }
69 
70  private void CheckVersion()
71  {
72  if (_expando._data.Version != _expandoVersion || _expandoData != _expando._data)
73  {
74  throw Error.CollectionModifiedWhileEnumerating();
75  }
76  }
77 
78  public void Add(string item)
79  {
80  throw Error.CollectionReadOnly();
81  }
82 
83  public void Clear()
84  {
85  throw Error.CollectionReadOnly();
86  }
87 
88  public bool Contains(string item)
89  {
90  lock (_expando.LockObject)
91  {
92  CheckVersion();
93  return _expando.ExpandoContainsKey(item);
94  }
95  }
96 
97  public void CopyTo(string[] array, int arrayIndex)
98  {
99  ContractUtils.RequiresNotNull(array, "array");
100  ContractUtils.RequiresArrayRange(array, arrayIndex, _expandoCount, "arrayIndex", "Count");
101  lock (_expando.LockObject)
102  {
103  CheckVersion();
104  ExpandoData data = _expando._data;
105  for (int i = 0; i < data.Class.Keys.Length; i++)
106  {
107  if (data[i] != Uninitialized)
108  {
109  array[arrayIndex++] = data.Class.Keys[i];
110  }
111  }
112  }
113  }
114 
115  public bool Remove(string item)
116  {
117  throw Error.CollectionReadOnly();
118  }
119 
120  public IEnumerator<string> GetEnumerator()
121  {
122  int j = 0;
123  for (int i = _expandoData.Class.Keys.Length; j < i; j++)
124  {
125  CheckVersion();
126  if (_expandoData[j] != Uninitialized)
127  {
128  yield return _expandoData.Class.Keys[j];
129  }
130  }
131  }
132 
134  {
135  return GetEnumerator();
136  }
137  }
138 
139  private sealed class ValueCollectionDebugView
140  {
141  private ICollection<object> collection;
142 
143  [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
144  public object[] Items
145  {
146  get
147  {
148  object[] array = new object[collection.Count];
149  collection.CopyTo(array, 0);
150  return array;
151  }
152  }
153 
154  public ValueCollectionDebugView(ICollection<object> collection)
155  {
156  this.collection = collection;
157  }
158  }
159 
160  [DebuggerTypeProxy(typeof(ValueCollectionDebugView))]
161  [DebuggerDisplay("Count = {Count}")]
162  private class ValueCollection : ICollection<object>, IEnumerable<object>, IEnumerable
163  {
164  private readonly ExpandoObject _expando;
165 
166  private readonly int _expandoVersion;
167 
168  private readonly int _expandoCount;
169 
170  private readonly ExpandoData _expandoData;
171 
172  public int Count
173  {
174  get
175  {
176  CheckVersion();
177  return _expandoCount;
178  }
179  }
180 
181  public bool IsReadOnly => true;
182 
183  internal ValueCollection(ExpandoObject expando)
184  {
185  lock (expando.LockObject)
186  {
187  _expando = expando;
188  _expandoVersion = expando._data.Version;
189  _expandoCount = expando._count;
190  _expandoData = expando._data;
191  }
192  }
193 
194  private void CheckVersion()
195  {
196  if (_expando._data.Version != _expandoVersion || _expandoData != _expando._data)
197  {
198  throw Error.CollectionModifiedWhileEnumerating();
199  }
200  }
201 
202  public void Add(object item)
203  {
204  throw Error.CollectionReadOnly();
205  }
206 
207  public void Clear()
208  {
209  throw Error.CollectionReadOnly();
210  }
211 
212  public bool Contains(object item)
213  {
214  lock (_expando.LockObject)
215  {
216  CheckVersion();
217  ExpandoData data = _expando._data;
218  for (int i = 0; i < data.Class.Keys.Length; i++)
219  {
220  if (object.Equals(data[i], item))
221  {
222  return true;
223  }
224  }
225  return false;
226  }
227  }
228 
229  public void CopyTo(object[] array, int arrayIndex)
230  {
231  ContractUtils.RequiresNotNull(array, "array");
232  ContractUtils.RequiresArrayRange(array, arrayIndex, _expandoCount, "arrayIndex", "Count");
233  lock (_expando.LockObject)
234  {
235  CheckVersion();
236  ExpandoData data = _expando._data;
237  for (int i = 0; i < data.Class.Keys.Length; i++)
238  {
239  if (data[i] != Uninitialized)
240  {
241  array[arrayIndex++] = data[i];
242  }
243  }
244  }
245  }
246 
247  public bool Remove(object item)
248  {
249  throw Error.CollectionReadOnly();
250  }
251 
252  public IEnumerator<object> GetEnumerator()
253  {
254  ExpandoData data = _expando._data;
255  for (int i = 0; i < data.Class.Keys.Length; i++)
256  {
257  CheckVersion();
258  object obj = data[i];
259  if (obj != Uninitialized)
260  {
261  yield return obj;
262  }
263  }
264  }
265 
267  {
268  return GetEnumerator();
269  }
270  }
271 
272  private class MetaExpando : DynamicMetaObject
273  {
274  public new ExpandoObject Value => (ExpandoObject)base.Value;
275 
276  public MetaExpando(Expression expression, ExpandoObject value)
277  : base(expression, BindingRestrictions.Empty, value)
278  {
279  }
280 
281  private DynamicMetaObject BindGetOrInvokeMember(DynamicMetaObjectBinder binder, string name, bool ignoreCase, DynamicMetaObject fallback, Func<DynamicMetaObject, DynamicMetaObject> fallbackInvoke)
282  {
283  ExpandoClass @class = Value.Class;
284  int valueIndex = @class.GetValueIndex(name, ignoreCase, Value);
285  ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "value");
286  Expression test = Expression.Call(typeof(RuntimeOps).GetMethod("ExpandoTryGetValue"), GetLimitedSelf(), Expression.Constant(@class, typeof(object)), Expression.Constant(valueIndex), Expression.Constant(name), Expression.Constant(ignoreCase), parameterExpression);
287  DynamicMetaObject dynamicMetaObject = new DynamicMetaObject(parameterExpression, BindingRestrictions.Empty);
288  if (fallbackInvoke != null)
289  {
290  dynamicMetaObject = fallbackInvoke(dynamicMetaObject);
291  }
292  dynamicMetaObject = new DynamicMetaObject(Expression.Block(new ParameterExpression[1]
293  {
294  parameterExpression
295  }, Expression.Condition(test, dynamicMetaObject.Expression, fallback.Expression, typeof(object))), dynamicMetaObject.Restrictions.Merge(fallback.Restrictions));
296  return AddDynamicTestAndDefer(binder, Value.Class, null, dynamicMetaObject);
297  }
298 
299  public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
300  {
301  ContractUtils.RequiresNotNull(binder, "binder");
302  return BindGetOrInvokeMember(binder, binder.Name, binder.IgnoreCase, binder.FallbackGetMember(this), null);
303  }
304 
305  public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
306  {
307  ContractUtils.RequiresNotNull(binder, "binder");
308  return BindGetOrInvokeMember(binder, binder.Name, binder.IgnoreCase, binder.FallbackInvokeMember(this, args), (DynamicMetaObject value) => binder.FallbackInvoke(value, args, null));
309  }
310 
311  public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
312  {
313  ContractUtils.RequiresNotNull(binder, "binder");
314  ContractUtils.RequiresNotNull(value, "value");
315  ExpandoClass klass;
316  int index;
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));
319  }
320 
321  public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder)
322  {
323  ContractUtils.RequiresNotNull(binder, "binder");
324  int valueIndex = Value.Class.GetValueIndex(binder.Name, binder.IgnoreCase, Value);
325  Expression expression = Expression.Call(typeof(RuntimeOps).GetMethod("ExpandoTryDeleteValue"), GetLimitedSelf(), Expression.Constant(Value.Class, typeof(object)), Expression.Constant(valueIndex), Expression.Constant(binder.Name), Expression.Constant(binder.IgnoreCase));
326  DynamicMetaObject dynamicMetaObject = binder.FallbackDeleteMember(this);
327  DynamicMetaObject succeeds = new DynamicMetaObject(Expression.IfThen(Expression.Not(expression), dynamicMetaObject.Expression), dynamicMetaObject.Restrictions);
328  return AddDynamicTestAndDefer(binder, Value.Class, null, succeeds);
329  }
330 
331  public override IEnumerable<string> GetDynamicMemberNames()
332  {
333  ExpandoData expandoData = Value._data;
334  ExpandoClass klass = expandoData.Class;
335  for (int i = 0; i < klass.Keys.Length; i++)
336  {
337  object obj = expandoData[i];
338  if (obj != Uninitialized)
339  {
340  yield return klass.Keys[i];
341  }
342  }
343  }
344 
345  private DynamicMetaObject AddDynamicTestAndDefer(DynamicMetaObjectBinder binder, ExpandoClass klass, ExpandoClass originalClass, DynamicMetaObject succeeds)
346  {
347  Expression expression = succeeds.Expression;
348  if (originalClass != null)
349  {
350  expression = Expression.Block(Expression.Call(null, typeof(RuntimeOps).GetMethod("ExpandoPromoteClass"), GetLimitedSelf(), Expression.Constant(originalClass, typeof(object)), Expression.Constant(klass, typeof(object))), succeeds.Expression);
351  }
352  return new DynamicMetaObject(Expression.Condition(Expression.Call(null, typeof(RuntimeOps).GetMethod("ExpandoCheckVersion"), GetLimitedSelf(), Expression.Constant(originalClass ?? klass, typeof(object))), expression, binder.GetUpdateExpression(expression.Type)), GetRestrictions().Merge(succeeds.Restrictions));
353  }
354 
355  private ExpandoClass GetClassEnsureIndex(string name, bool caseInsensitive, ExpandoObject obj, out ExpandoClass klass, out int index)
356  {
357  ExpandoClass @class = Value.Class;
358  index = @class.GetValueIndex(name, caseInsensitive, obj);
359  if (index == -2)
360  {
361  klass = @class;
362  return null;
363  }
364  if (index == -1)
365  {
366  index = (klass = @class.FindNewClass(name)).GetValueIndexCaseSensitive(name);
367  return @class;
368  }
369  klass = @class;
370  return null;
371  }
372 
373  private Expression GetLimitedSelf()
374  {
375  if (TypeUtils.AreEquivalent(base.Expression.Type, base.LimitType))
376  {
377  return base.Expression;
378  }
379  return Expression.Convert(base.Expression, base.LimitType);
380  }
381 
382  private BindingRestrictions GetRestrictions()
383  {
385  }
386  }
387 
388  private class ExpandoData
389  {
390  internal static ExpandoData Empty = new ExpandoData();
391 
392  internal readonly ExpandoClass Class;
393 
394  private readonly object[] _dataArray;
395 
396  private int _version;
397 
398  internal object this[int index]
399  {
400  get
401  {
402  return _dataArray[index];
403  }
404  set
405  {
406  _version++;
407  _dataArray[index] = value;
408  }
409  }
410 
411  internal int Version => _version;
412 
413  internal int Length => _dataArray.Length;
414 
415  private ExpandoData()
416  {
417  Class = ExpandoClass.Empty;
418  _dataArray = new object[0];
419  }
420 
421  internal ExpandoData(ExpandoClass klass, object[] data, int version)
422  {
423  Class = klass;
424  _dataArray = data;
425  _version = version;
426  }
427 
428  internal ExpandoData UpdateClass(ExpandoClass newClass)
429  {
430  if (_dataArray.Length >= newClass.Keys.Length)
431  {
432  this[newClass.Keys.Length - 1] = Uninitialized;
433  return new ExpandoData(newClass, _dataArray, _version);
434  }
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;
440  return expandoData;
441  }
442 
443  private static int GetAlignedSize(int len)
444  {
445  return (len + 7) & -8;
446  }
447  }
448 
449  internal readonly object LockObject;
450 
451  private ExpandoData _data;
452 
453  private int _count;
454 
455  internal static readonly object Uninitialized = new object();
456 
457  internal const int AmbiguousMatchFound = -2;
458 
459  internal const int NoMatch = -1;
460 
461  private PropertyChangedEventHandler _propertyChanged;
462 
463  internal ExpandoClass Class => _data.Class;
464 
465  [global::__DynamicallyInvokable]
467  {
468  [global::__DynamicallyInvokable]
469  get
470  {
471  return new KeyCollection(this);
472  }
473  }
474 
475  [global::__DynamicallyInvokable]
477  {
478  [global::__DynamicallyInvokable]
479  get
480  {
481  return new ValueCollection(this);
482  }
483  }
484 
485  [global::__DynamicallyInvokable]
486  object IDictionary<string, object>.this[string key]
487  {
488  [global::__DynamicallyInvokable]
489  get
490  {
491  if (!TryGetValueForKey(key, out object value))
492  {
493  throw Error.KeyDoesNotExistInExpando(key);
494  }
495  return value;
496  }
497  [global::__DynamicallyInvokable]
498  set
499  {
500  ContractUtils.RequiresNotNull(key, "key");
501  TrySetValue(null, -1, value, key, ignoreCase: false, add: false);
502  }
503  }
504 
505  [global::__DynamicallyInvokable]
507  {
508  [global::__DynamicallyInvokable]
509  get
510  {
511  return _count;
512  }
513  }
514 
515  [global::__DynamicallyInvokable]
517  {
518  [global::__DynamicallyInvokable]
519  get
520  {
521  return false;
522  }
523  }
524 
526  [global::__DynamicallyInvokable]
528  {
529  [global::__DynamicallyInvokable]
530  add
531  {
532  _propertyChanged = (PropertyChangedEventHandler)Delegate.Combine(_propertyChanged, value);
533  }
534  [global::__DynamicallyInvokable]
535  remove
536  {
537  _propertyChanged = (PropertyChangedEventHandler)Delegate.Remove(_propertyChanged, value);
538  }
539  }
540 
542  [global::__DynamicallyInvokable]
543  public ExpandoObject()
544  {
545  _data = ExpandoData.Empty;
546  LockObject = new object();
547  }
548 
549  internal bool TryGetValue(object indexClass, int index, string name, bool ignoreCase, out object value)
550  {
551  ExpandoData data = _data;
552  if ((data.Class != indexClass) | ignoreCase)
553  {
554  index = data.Class.GetValueIndex(name, ignoreCase, this);
555  if (index == -2)
556  {
557  throw Error.AmbiguousMatchInExpandoObject(name);
558  }
559  }
560  if (index == -1)
561  {
562  value = null;
563  return false;
564  }
565  object obj = data[index];
566  if (obj == Uninitialized)
567  {
568  value = null;
569  return false;
570  }
571  value = obj;
572  return true;
573  }
574 
575  internal void TrySetValue(object indexClass, int index, object value, string name, bool ignoreCase, bool add)
576  {
577  ExpandoData expandoData;
578  object obj;
579  lock (LockObject)
580  {
581  expandoData = _data;
582  if ((expandoData.Class != indexClass) | ignoreCase)
583  {
584  index = expandoData.Class.GetValueIndex(name, ignoreCase, this);
585  switch (index)
586  {
587  case -2:
588  throw Error.AmbiguousMatchInExpandoObject(name);
589  case -1:
590  {
591  int num = ignoreCase ? expandoData.Class.GetValueIndexCaseSensitive(name) : index;
592  if (num != -1)
593  {
594  index = num;
595  }
596  else
597  {
598  ExpandoClass newClass = expandoData.Class.FindNewClass(name);
599  expandoData = PromoteClassCore(expandoData.Class, newClass);
600  index = expandoData.Class.GetValueIndexCaseSensitive(name);
601  }
602  break;
603  }
604  }
605  }
606  obj = expandoData[index];
607  if (obj == Uninitialized)
608  {
609  _count++;
610  }
611  else if (add)
612  {
613  throw Error.SameKeyExistsInExpando(name);
614  }
615  expandoData[index] = value;
616  }
617  PropertyChangedEventHandler propertyChanged = _propertyChanged;
618  if (propertyChanged != null && value != obj)
619  {
620  propertyChanged(this, new PropertyChangedEventArgs(expandoData.Class.Keys[index]));
621  }
622  }
623 
624  internal bool TryDeleteValue(object indexClass, int index, string name, bool ignoreCase, object deleteValue)
625  {
626  ExpandoData data;
627  lock (LockObject)
628  {
629  data = _data;
630  if ((data.Class != indexClass) | ignoreCase)
631  {
632  index = data.Class.GetValueIndex(name, ignoreCase, this);
633  if (index == -2)
634  {
635  throw Error.AmbiguousMatchInExpandoObject(name);
636  }
637  }
638  if (index == -1)
639  {
640  return false;
641  }
642  object obj = data[index];
643  if (obj == Uninitialized)
644  {
645  return false;
646  }
647  if (deleteValue != Uninitialized && !object.Equals(obj, deleteValue))
648  {
649  return false;
650  }
651  data[index] = Uninitialized;
652  _count--;
653  }
654  _propertyChanged?.Invoke(this, new PropertyChangedEventArgs(data.Class.Keys[index]));
655  return true;
656  }
657 
658  internal bool IsDeletedMember(int index)
659  {
660  if (index == _data.Length)
661  {
662  return false;
663  }
664  return _data[index] == Uninitialized;
665  }
666 
667  private ExpandoData PromoteClassCore(ExpandoClass oldClass, ExpandoClass newClass)
668  {
669  lock (LockObject)
670  {
671  if (_data.Class == oldClass)
672  {
673  _data = _data.UpdateClass(newClass);
674  }
675  return _data;
676  }
677  }
678 
679  internal void PromoteClass(object oldClass, object newClass)
680  {
681  PromoteClassCore((ExpandoClass)oldClass, (ExpandoClass)newClass);
682  }
683 
687  [global::__DynamicallyInvokable]
688  DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
689  {
690  return new MetaExpando(parameter, this);
691  }
692 
693  private void TryAddMember(string key, object value)
694  {
695  ContractUtils.RequiresNotNull(key, "key");
696  TrySetValue(null, -1, value, key, ignoreCase: false, add: true);
697  }
698 
699  private bool TryGetValueForKey(string key, out object value)
700  {
701  return TryGetValue(null, -1, key, ignoreCase: false, out value);
702  }
703 
704  private bool ExpandoContainsKey(string key)
705  {
706  return _data.Class.GetValueIndexCaseSensitive(key) >= 0;
707  }
708 
709  [global::__DynamicallyInvokable]
710  void IDictionary<string, object>.Add(string key, object value)
711  {
712  TryAddMember(key, value);
713  }
714 
715  [global::__DynamicallyInvokable]
716  bool IDictionary<string, object>.ContainsKey(string key)
717  {
718  ContractUtils.RequiresNotNull(key, "key");
719  ExpandoData data = _data;
720  int valueIndexCaseSensitive = data.Class.GetValueIndexCaseSensitive(key);
721  if (valueIndexCaseSensitive >= 0)
722  {
723  return data[valueIndexCaseSensitive] != Uninitialized;
724  }
725  return false;
726  }
727 
728  [global::__DynamicallyInvokable]
729  bool IDictionary<string, object>.Remove(string key)
730  {
731  ContractUtils.RequiresNotNull(key, "key");
732  return TryDeleteValue(null, -1, key, ignoreCase: false, Uninitialized);
733  }
734 
735  [global::__DynamicallyInvokable]
736  bool IDictionary<string, object>.TryGetValue(string key, out object value)
737  {
738  return TryGetValueForKey(key, out value);
739  }
740 
741  [global::__DynamicallyInvokable]
743  {
744  TryAddMember(item.Key, item.Value);
745  }
746 
747  [global::__DynamicallyInvokable]
749  {
750  ExpandoData data;
751  lock (LockObject)
752  {
753  data = _data;
754  _data = ExpandoData.Empty;
755  _count = 0;
756  }
757  PropertyChangedEventHandler propertyChanged = _propertyChanged;
758  if (propertyChanged == null)
759  {
760  return;
761  }
762  int i = 0;
763  for (int num = data.Class.Keys.Length; i < num; i++)
764  {
765  if (data[i] != Uninitialized)
766  {
767  propertyChanged(this, new PropertyChangedEventArgs(data.Class.Keys[i]));
768  }
769  }
770  }
771 
772  [global::__DynamicallyInvokable]
774  {
775  if (!TryGetValueForKey(item.Key, out object value))
776  {
777  return false;
778  }
779  return object.Equals(value, item.Value);
780  }
781 
782  [global::__DynamicallyInvokable]
784  {
785  ContractUtils.RequiresNotNull(array, "array");
786  ContractUtils.RequiresArrayRange(array, arrayIndex, _count, "arrayIndex", "Count");
787  lock (LockObject)
788  {
790  {
791  array[arrayIndex++] = item;
792  }
793  }
794  }
795 
796  [global::__DynamicallyInvokable]
798  {
799  return TryDeleteValue(null, -1, item.Key, ignoreCase: false, item.Value);
800  }
801 
802  [global::__DynamicallyInvokable]
804  {
805  ExpandoData data = _data;
806  return GetExpandoEnumerator(data, data.Version);
807  }
808 
811  [global::__DynamicallyInvokable]
813  {
814  ExpandoData data = _data;
815  return GetExpandoEnumerator(data, data.Version);
816  }
817 
818  private IEnumerator<KeyValuePair<string, object>> GetExpandoEnumerator(ExpandoData data, int version)
819  {
820  int i = 0;
821  while (true)
822  {
823  if (i < data.Class.Keys.Length)
824  {
825  if (_data.Version != version || data != _data)
826  {
827  break;
828  }
829  object obj = data[i];
830  if (obj != Uninitialized)
831  {
832  yield return new KeyValuePair<string, object>(data.Class.Keys[i], obj);
833  }
834  i++;
835  continue;
836  }
837  yield break;
838  }
839  throw Error.CollectionModifiedWhileEnumerating();
840  }
841  }
842 }
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.
Represents a dynamic object, that can have its operations bound at runtime.
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 binding and a binding logic of an object participating in the dynamic binding.
Represents the dynamic set member operation at the call site, providing the binding semantic and the ...
Definition: __Canon.cs:3
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 ...
Definition: Delegate.cs:287
static Delegate Combine(Delegate a, Delegate b)
Concatenates the invocation lists of two delegates.
Definition: Delegate.cs:202
BindingRestrictions Merge(BindingRestrictions restrictions)
Merges the set of binding restrictions with the current binding restrictions.
Expression Expression
The expression representing the T:System.Dynamic.DynamicMetaObject during the dynamic binding process...
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.
Definition: KeyValuePair.cs:10
Exposes an enumerator, which supports a simple iteration over a non-generic collection....
Definition: IEnumerable.cs:9
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....
Definition: Expression.cs:17
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.
BindingRestrictions Restrictions
The set of binding restrictions under which the binding is valid.
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...
Definition: Array.cs:17
Represents a delegate, which is a data structure that refers to a static method or to a class instanc...
Definition: Delegate.cs:15
The dynamic call site binder that participates in the T:System.Dynamic.DynamicMetaObject binding prot...
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....
Definition: Version.cs:11
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....
Definition: IDictionary.cs:29
ICollection Values
Gets an T:System.Collections.ICollection object containing the values in the T:System....
Definition: IDictionary.cs:38
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 ...
Definition: Array.cs:1275
bool IgnoreCase
Gets the value indicating if the string comparison should ignore the case of the member name.
Expression GetUpdateExpression(Type type)
Gets an expression that will cause the binding to be updated. It indicates that the expression's bind...
int Count
Gets the number of elements contained in the T:System.Collections.ICollection.
Definition: ICollection.cs:14
Defines size, enumerators, and synchronization methods for all nongeneric collections.
Definition: ICollection.cs:8
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.
Definition: IDictionary.cs:8
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.
Definition: RuntimeOps.cs:16