Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ExpandoObject.cs
Go to the documentation of this file.
9
10namespace System.Dynamic;
11
12public sealed class ExpandoObject : IDynamicMetaObjectProvider, IDictionary<string, object?>, ICollection<KeyValuePair<string, object?>>, IEnumerable<KeyValuePair<string, object?>>, IEnumerable, INotifyPropertyChanged
13{
14 private sealed class KeyCollectionDebugView
15 {
17
19 public string[] Items
20 {
21 get
22 {
23 string[] array = new string[_collection.Count];
25 return array;
26 }
27 }
28
34 }
35
36 [DebuggerTypeProxy(typeof(KeyCollectionDebugView))]
37 [DebuggerDisplay("Count = {Count}")]
38 private sealed 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 {
53 return _expandoCount;
54 }
55 }
56
57 public bool IsReadOnly => true;
58
60 {
61 lock (expando.LockObject)
62 {
64 _expandoVersion = expando._data.Version;
66 _expandoData = expando._data;
67 }
68 }
69
77
78 public void Add(string item)
79 {
81 }
82
83 public void Clear()
84 {
86 }
87
88 public bool Contains(string item)
89 {
91 {
94 }
95 }
96
97 public void CopyTo(string[] array, int arrayIndex)
98 {
100 ContractUtils.RequiresArrayRange(array, arrayIndex, _expandoCount, "arrayIndex", "Count");
102 {
103 CheckVersion();
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 {
118 }
119
121 {
122 int i = 0;
123 for (int j = _expandoData.Class.Keys.Length; i < j; i++)
124 {
125 CheckVersion();
126 if (_expandoData[i] != Uninitialized)
127 {
128 yield return _expandoData.Class.Keys[i];
129 }
130 }
131 }
132
137 }
138
139 private sealed class ValueCollectionDebugView
140 {
142
144 public object[] Items
145 {
146 get
147 {
148 object[] array = new object[_collection.Count];
150 return array;
151 }
152 }
153
159 }
160
161 [DebuggerTypeProxy(typeof(ValueCollectionDebugView))]
162 [DebuggerDisplay("Count = {Count}")]
163 private sealed class ValueCollection : ICollection<object>, IEnumerable<object>, IEnumerable
164 {
165 private readonly ExpandoObject _expando;
166
167 private readonly int _expandoVersion;
168
169 private readonly int _expandoCount;
170
171 private readonly ExpandoData _expandoData;
172
173 public int Count
174 {
175 get
176 {
177 CheckVersion();
178 return _expandoCount;
179 }
180 }
181
182 public bool IsReadOnly => true;
183
185 {
186 lock (expando.LockObject)
187 {
189 _expandoVersion = expando._data.Version;
191 _expandoData = expando._data;
192 }
193 }
194
195 private void CheckVersion()
196 {
198 {
200 }
201 }
202
203 public void Add(object item)
204 {
206 }
207
208 public void Clear()
209 {
211 }
212
213 public bool Contains(object item)
214 {
216 {
217 CheckVersion();
219 for (int i = 0; i < data.Class.Keys.Length; i++)
220 {
221 if (object.Equals(data[i], item))
222 {
223 return true;
224 }
225 }
226 return false;
227 }
228 }
229
230 public void CopyTo(object[] array, int arrayIndex)
231 {
233 ContractUtils.RequiresArrayRange(array, arrayIndex, _expandoCount, "arrayIndex", "Count");
235 {
236 CheckVersion();
238 for (int i = 0; i < data.Class.Keys.Length; i++)
239 {
240 if (data[i] != Uninitialized)
241 {
242 array[arrayIndex++] = data[i];
243 }
244 }
245 }
246 }
247
248 public bool Remove(object item)
249 {
251 }
252
254 {
256 for (int i = 0; i < data.Class.Keys.Length; i++)
257 {
258 CheckVersion();
259 object obj = data[i];
260 if (obj != Uninitialized)
261 {
262 yield return obj;
263 }
264 }
265 }
266
271 }
272
273 private sealed class MetaExpando : DynamicMetaObject
274 {
275 public new ExpandoObject Value => (ExpandoObject)base.Value;
276
281
296
298 {
300 return BindGetOrInvokeMember(binder, binder.Name, binder.IgnoreCase, binder.FallbackGetMember(this), null);
301 }
302
304 {
306 return BindGetOrInvokeMember(binder, binder.Name, binder.IgnoreCase, binder.FallbackInvokeMember(this, args), (DynamicMetaObject value) => binder.FallbackInvoke(value, args, null));
307 }
308
318
328
330 {
333 for (int i = 0; i < klass.Keys.Length; i++)
334 {
335 object obj = expandoData[i];
336 if (obj != Uninitialized)
337 {
338 yield return klass.Keys[i];
339 }
340 }
341 }
342
352
353 private ExpandoClass GetClassEnsureIndex(string name, bool caseInsensitive, ExpandoObject obj, out ExpandoClass klass, out int index)
354 {
355 ExpandoClass @class = Value.Class;
356 index = @class.GetValueIndex(name, caseInsensitive, obj);
357 if (index == -2)
358 {
359 klass = @class;
360 return null;
361 }
362 if (index == -1)
363 {
364 index = (klass = @class.FindNewClass(name)).GetValueIndexCaseSensitive(name);
365 return @class;
366 }
367 klass = @class;
368 return null;
369 }
370
372 {
373 if (TypeUtils.AreEquivalent(base.Expression.Type, base.LimitType))
374 {
375 return base.Expression;
376 }
377 return System.Linq.Expressions.Expression.Convert(base.Expression, base.LimitType);
378 }
379
384 }
385
386 private sealed class ExpandoData
387 {
388 internal static ExpandoData Empty = new ExpandoData();
389
390 internal readonly ExpandoClass Class;
391
392 private readonly object[] _dataArray;
393
394 private int _version;
395
396 internal object this[int index]
397 {
398 get
399 {
400 return _dataArray[index];
401 }
402 set
403 {
404 _version++;
406 }
407 }
408
409 internal int Version => _version;
410
411 internal int Length => _dataArray.Length;
412
413 private ExpandoData()
414 {
416 _dataArray = Array.Empty<object>();
417 }
418
419 internal ExpandoData(ExpandoClass klass, object[] data, int version)
420 {
421 Class = klass;
422 _dataArray = data;
423 _version = version;
424 }
425
427 {
428 if (_dataArray.Length >= newClass.Keys.Length)
429 {
430 this[newClass.Keys.Length - 1] = Uninitialized;
432 }
433 int index = _dataArray.Length;
434 object[] array = new object[GetAlignedSize(newClass.Keys.Length)];
438 return expandoData;
439 }
440
441 private static int GetAlignedSize(int len)
442 {
443 return (len + 7) & -8;
444 }
445 }
446
447 private static readonly MethodInfo s_expandoTryGetValue = typeof(RuntimeOps).GetMethod("ExpandoTryGetValue");
448
449 private static readonly MethodInfo s_expandoTrySetValue = typeof(RuntimeOps).GetMethod("ExpandoTrySetValue");
450
451 private static readonly MethodInfo s_expandoTryDeleteValue = typeof(RuntimeOps).GetMethod("ExpandoTryDeleteValue");
452
453 private static readonly MethodInfo s_expandoPromoteClass = typeof(RuntimeOps).GetMethod("ExpandoPromoteClass");
454
455 private static readonly MethodInfo s_expandoCheckVersion = typeof(RuntimeOps).GetMethod("ExpandoCheckVersion");
456
457 internal readonly object LockObject;
458
460
461 private int _count;
462
463 internal static readonly object Uninitialized = new object();
464
465 private PropertyChangedEventHandler _propertyChanged;
466
468
470
472
473 object? IDictionary<string, object>.this[string key]
474 {
475 get
476 {
478 {
480 }
481 return value;
482 }
483 set
484 {
486 TrySetValue(null, -1, value, key, ignoreCase: false, add: false);
487 }
488 }
489
491
493
494 event PropertyChangedEventHandler? INotifyPropertyChanged.PropertyChanged
495 {
496 add
497 {
499 }
500 remove
501 {
503 }
504 }
505
507 {
509 LockObject = new object();
510 }
511
512 internal bool TryGetValue(object indexClass, int index, string name, bool ignoreCase, out object value)
513 {
514 ExpandoData data = _data;
515 if (data.Class != indexClass || ignoreCase)
516 {
517 index = data.Class.GetValueIndex(name, ignoreCase, this);
518 if (index == -2)
519 {
521 }
522 }
523 if (index == -1)
524 {
525 value = null;
526 return false;
527 }
528 object obj = data[index];
529 if (obj == Uninitialized)
530 {
531 value = null;
532 return false;
533 }
534 value = obj;
535 return true;
536 }
537
538 internal void TrySetValue(object indexClass, int index, object value, string name, bool ignoreCase, bool add)
539 {
541 object obj;
543 {
545 if (expandoData.Class != indexClass || ignoreCase)
546 {
547 index = expandoData.Class.GetValueIndex(name, ignoreCase, this);
548 switch (index)
549 {
550 case -2:
552 case -1:
553 {
554 int num = (ignoreCase ? expandoData.Class.GetValueIndexCaseSensitive(name) : index);
555 if (num != -1)
556 {
557 index = num;
558 break;
559 }
560 ExpandoClass newClass = expandoData.Class.FindNewClass(name);
562 index = expandoData.Class.GetValueIndexCaseSensitive(name);
563 break;
564 }
565 }
566 }
568 if (obj == Uninitialized)
569 {
570 _count++;
571 }
572 else if (add)
573 {
574 throw Error.SameKeyExistsInExpando(name);
575 }
577 }
578 PropertyChangedEventHandler propertyChanged = _propertyChanged;
579 if (propertyChanged != null && value != obj)
580 {
582 }
583 }
584
585 internal bool TryDeleteValue(object indexClass, int index, string name, bool ignoreCase, object deleteValue)
586 {
587 ExpandoData data;
589 {
590 data = _data;
591 if (data.Class != indexClass || ignoreCase)
592 {
593 index = data.Class.GetValueIndex(name, ignoreCase, this);
594 if (index == -2)
595 {
597 }
598 }
599 if (index == -1)
600 {
601 return false;
602 }
603 object obj = data[index];
604 if (obj == Uninitialized)
605 {
606 return false;
607 }
608 if (deleteValue != Uninitialized && !object.Equals(obj, deleteValue))
609 {
610 return false;
611 }
612 data[index] = Uninitialized;
613 _count--;
614 }
615 _propertyChanged?.Invoke(this, new PropertyChangedEventArgs(data.Class.Keys[index]));
616 return true;
617 }
618
619 internal bool IsDeletedMember(int index)
620 {
621 if (index == _data.Length)
622 {
623 return false;
624 }
625 return _data[index] == Uninitialized;
626 }
627
636
637 internal void PromoteClass(object oldClass, object newClass)
638 {
640 {
642 }
643 }
644
649
650 private void TryAddMember(string key, object value)
651 {
653 TrySetValue(null, -1, value, key, ignoreCase: false, add: true);
654 }
655
656 private bool TryGetValueForKey(string key, out object value)
657 {
658 return TryGetValue(null, -1, key, ignoreCase: false, out value);
659 }
660
661 private bool ExpandoContainsKey(string key)
662 {
664 }
665
667 {
669 }
670
672 {
674 ExpandoData data = _data;
677 {
679 }
680 return false;
681 }
682
684 {
686 return TryDeleteValue(null, -1, key, ignoreCase: false, Uninitialized);
687 }
688
690 {
692 }
693
698
700 {
701 ExpandoData data;
703 {
704 data = _data;
706 _count = 0;
707 }
708 PropertyChangedEventHandler propertyChanged = _propertyChanged;
709 if (propertyChanged == null)
710 {
711 return;
712 }
713 int i = 0;
714 for (int num = data.Class.Keys.Length; i < num; i++)
715 {
716 if (data[i] != Uninitialized)
717 {
719 }
720 }
721 }
722
724 {
726 {
727 return false;
728 }
729 return object.Equals(value, item.Value);
730 }
731
733 {
736 {
737 ContractUtils.RequiresArrayRange(array, arrayIndex, _count, "arrayIndex", "Count");
739 {
740 array[arrayIndex++] = item;
741 }
742 }
743 }
744
749
755
757 {
758 ExpandoData data = _data;
759 return GetExpandoEnumerator(data, data.Version);
760 }
761
763 {
764 for (int i = 0; i < data.Class.Keys.Length; i++)
765 {
766 if (_data.Version != version || data != _data)
767 {
769 }
770 object obj = data[i];
771 if (obj != Uninitialized)
772 {
773 yield return new KeyValuePair<string, object>(data.Class.Keys[i], obj);
774 }
775 }
776 }
777}
static unsafe void Copy(Array sourceArray, Array destinationArray, int length)
Definition Array.cs:624
bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
bool ICollection< KeyValuePair< TKey, TValue > >. Remove(KeyValuePair< TKey, TValue > keyValuePair)
void CopyTo(KeyValuePair< TKey, TValue >[] array, int index)
bool ICollection< KeyValuePair< TKey, TValue > >. Contains(KeyValuePair< TKey, TValue > keyValuePair)
bool ICollection< KeyValuePair< TKey, TValue > >. IsReadOnly
void Add(TKey key, TValue value)
static ? Delegate Remove(Delegate? source, Delegate? value)
Definition Delegate.cs:463
static ? Delegate Combine(Delegate? a, Delegate? b)
Definition Delegate.cs:379
static readonly BindingRestrictions Empty
static BindingRestrictions GetTypeRestriction(Expression expression, Type type)
DynamicMetaObject(Expression expression, BindingRestrictions restrictions)
static readonly ExpandoClass Empty
int GetValueIndex(string name, bool caseInsensitive, ExpandoObject obj)
int GetValueIndexCaseSensitive(string name)
ExpandoData UpdateClass(ExpandoClass newClass)
ExpandoData(ExpandoClass klass, object[] data, int version)
KeyCollectionDebugView(ICollection< string > collection)
void CopyTo(string[] array, int arrayIndex)
override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder)
ExpandoClass GetClassEnsureIndex(string name, bool caseInsensitive, ExpandoObject obj, out ExpandoClass klass, out int index)
override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
DynamicMetaObject AddDynamicTestAndDefer(DynamicMetaObjectBinder binder, ExpandoClass klass, ExpandoClass originalClass, DynamicMetaObject succeeds)
override IEnumerable< string > GetDynamicMemberNames()
MetaExpando(Expression expression, ExpandoObject value)
override DynamicMetaObject BindGetMember(GetMemberBinder binder)
DynamicMetaObject BindGetOrInvokeMember(DynamicMetaObjectBinder binder, string name, bool ignoreCase, DynamicMetaObject fallback, Func< DynamicMetaObject, DynamicMetaObject > fallbackInvoke)
ValueCollectionDebugView(ICollection< object > collection)
void CopyTo(object[] array, int arrayIndex)
bool TryGetValue(object indexClass, int index, string name, bool ignoreCase, out object value)
void PromoteClass(object oldClass, object newClass)
IEnumerator< KeyValuePair< string, object > > GetExpandoEnumerator(ExpandoData data, int version)
static readonly MethodInfo s_expandoTryGetValue
bool ExpandoContainsKey(string key)
void TrySetValue(object indexClass, int index, object value, string name, bool ignoreCase, bool add)
static readonly MethodInfo s_expandoTrySetValue
static readonly MethodInfo s_expandoPromoteClass
ExpandoData PromoteClassCore(ExpandoClass oldClass, ExpandoClass newClass)
PropertyChangedEventHandler _propertyChanged
static readonly object Uninitialized
void TryAddMember(string key, object value)
bool TryGetValueForKey(string key, out object value)
static readonly MethodInfo s_expandoCheckVersion
static readonly MethodInfo s_expandoTryDeleteValue
bool TryDeleteValue(object indexClass, int index, string name, bool ignoreCase, object deleteValue)
static void RequiresNotNull(object value, string paramName)
static bool AreEquivalent(Type t1, Type t2)
Definition TypeUtils.cs:664
static Exception CollectionModifiedWhileEnumerating()
Definition Error.cs:38
static Exception KeyDoesNotExistInExpando(object p0)
Definition Error.cs:33
static Exception CollectionReadOnly()
Definition Error.cs:43
static Exception AmbiguousMatchInExpandoObject(object p0)
Definition Error.cs:23
static Exception SameKeyExistsInExpando(object key)
Definition Error.cs:28
static ConstantExpression Constant(object? value)
static BlockExpression Block(Expression arg0, Expression arg1)
static MethodCallExpression Call(MethodInfo method)
static ParameterExpression Parameter(Type type)
static UnaryExpression Not(Expression expression)
static ConditionalExpression Condition(Expression test, Expression ifTrue, Expression ifFalse)
static ConditionalExpression IfThen(Expression test, Expression ifTrue)
static UnaryExpression Convert(Expression expression, Type type)
static ConstantExpression Constant(bool value)
Definition Utils.cs:64
void CopyTo(T[] array, int arrayIndex)
new IEnumerator< T > GetEnumerator()
DynamicMetaObject GetMetaObject(Expression parameter)
delegate void PropertyChangedEventHandler(object? sender, PropertyChangedEventArgs e)