mscorlib(4.0.0.0) API with additions
MulticastDelegate.cs
1 using System.Diagnostics;
2 using System.Reflection;
6 using System.Security;
7 using System.Threading;
8 
9 namespace System
10 {
12  [Serializable]
13  [ComVisible(true)]
14  [__DynamicallyInvokable]
15  public abstract class MulticastDelegate : Delegate
16  {
17  [SecurityCritical]
18  private object _invocationList;
19 
20  [SecurityCritical]
21  private IntPtr _invocationCount;
22 
27  protected MulticastDelegate(object target, string method)
28  : base(target, method)
29  {
30  }
31 
36  protected MulticastDelegate(Type target, string method)
37  : base(target, method)
38  {
39  }
40 
41  [SecuritySafeCritical]
42  internal bool IsUnmanagedFunctionPtr()
43  {
44  return _invocationCount == (IntPtr)(-1);
45  }
46 
47  [SecuritySafeCritical]
48  internal bool InvocationListLogicallyNull()
49  {
50  if (_invocationList != null && !(_invocationList is LoaderAllocator))
51  {
52  return _invocationList is DynamicResolver;
53  }
54  return true;
55  }
56 
64  [SecurityCritical]
65  public override void GetObjectData(SerializationInfo info, StreamingContext context)
66  {
67  int num = 0;
68  object[] array = _invocationList as object[];
69  if (array == null)
70  {
71  MethodInfo method = base.Method;
72  if (!(method is RuntimeMethodInfo) || IsUnmanagedFunctionPtr())
73  {
74  throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
75  }
76  if (!InvocationListLogicallyNull() && !_invocationCount.IsNull() && !_methodPtrAux.IsNull())
77  {
78  throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
79  }
80  DelegateSerializationHolder.GetDelegateSerializationInfo(info, GetType(), base.Target, method, num);
81  return;
82  }
83  DelegateSerializationHolder.DelegateEntry delegateEntry = null;
84  int num2 = (int)_invocationCount;
85  int num3 = num2;
86  while (--num3 >= 0)
87  {
88  MulticastDelegate multicastDelegate = (MulticastDelegate)array[num3];
89  MethodInfo method2 = multicastDelegate.Method;
90  if (method2 is RuntimeMethodInfo && !IsUnmanagedFunctionPtr() && (multicastDelegate.InvocationListLogicallyNull() || multicastDelegate._invocationCount.IsNull() || multicastDelegate._methodPtrAux.IsNull()))
91  {
92  DelegateSerializationHolder.DelegateEntry delegateSerializationInfo = DelegateSerializationHolder.GetDelegateSerializationInfo(info, multicastDelegate.GetType(), multicastDelegate.Target, method2, num++);
93  if (delegateEntry != null)
94  {
95  delegateEntry.Entry = delegateSerializationInfo;
96  }
97  delegateEntry = delegateSerializationInfo;
98  }
99  }
100  if (delegateEntry != null)
101  {
102  return;
103  }
104  throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
105  }
106 
112  [SecuritySafeCritical]
113  [__DynamicallyInvokable]
114  public sealed override bool Equals(object obj)
115  {
116  if (obj == null || !Delegate.InternalEqualTypes(this, obj))
117  {
118  return false;
119  }
120  MulticastDelegate multicastDelegate = obj as MulticastDelegate;
121  if ((object)multicastDelegate == null)
122  {
123  return false;
124  }
125  if (_invocationCount != (IntPtr)0)
126  {
127  if (InvocationListLogicallyNull())
128  {
129  if (IsUnmanagedFunctionPtr())
130  {
131  if (!multicastDelegate.IsUnmanagedFunctionPtr())
132  {
133  return false;
134  }
135  return Delegate.CompareUnmanagedFunctionPtrs(this, multicastDelegate);
136  }
137  if (multicastDelegate._invocationList is Delegate)
138  {
139  return Equals(multicastDelegate._invocationList);
140  }
141  return base.Equals(obj);
142  }
143  if (_invocationList is Delegate)
144  {
145  return _invocationList.Equals(obj);
146  }
147  return InvocationListEquals(multicastDelegate);
148  }
149  if (!InvocationListLogicallyNull())
150  {
151  if (!_invocationList.Equals(multicastDelegate._invocationList))
152  {
153  return false;
154  }
155  return base.Equals((object)multicastDelegate);
156  }
157  if (multicastDelegate._invocationList is Delegate)
158  {
159  return Equals(multicastDelegate._invocationList);
160  }
161  return base.Equals((object)multicastDelegate);
162  }
163 
164  [SecuritySafeCritical]
165  private bool InvocationListEquals(MulticastDelegate d)
166  {
167  object[] array = _invocationList as object[];
168  if (d._invocationCount != _invocationCount)
169  {
170  return false;
171  }
172  int num = (int)_invocationCount;
173  for (int i = 0; i < num; i++)
174  {
175  Delegate @delegate = (Delegate)array[i];
176  object[] array2 = d._invocationList as object[];
177  if (!@delegate.Equals(array2[i]))
178  {
179  return false;
180  }
181  }
182  return true;
183  }
184 
185  [SecurityCritical]
186  private bool TrySetSlot(object[] a, int index, object o)
187  {
188  if (a[index] == null && Interlocked.CompareExchange<object>(ref a[index], o, (object)null) == null)
189  {
190  return true;
191  }
192  if (a[index] != null)
193  {
194  MulticastDelegate multicastDelegate = (MulticastDelegate)o;
195  MulticastDelegate multicastDelegate2 = (MulticastDelegate)a[index];
196  if (multicastDelegate2._methodPtr == multicastDelegate._methodPtr && multicastDelegate2._target == multicastDelegate._target && multicastDelegate2._methodPtrAux == multicastDelegate._methodPtrAux)
197  {
198  return true;
199  }
200  }
201  return false;
202  }
203 
204  [SecurityCritical]
205  private MulticastDelegate NewMulticastDelegate(object[] invocationList, int invocationCount, bool thisIsMultiCastAlready)
206  {
207  MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
208  if (thisIsMultiCastAlready)
209  {
210  multicastDelegate._methodPtr = _methodPtr;
211  multicastDelegate._methodPtrAux = _methodPtrAux;
212  }
213  else
214  {
215  multicastDelegate._methodPtr = GetMulticastInvoke();
216  multicastDelegate._methodPtrAux = GetInvokeMethod();
217  }
218  multicastDelegate._target = multicastDelegate;
219  multicastDelegate._invocationList = invocationList;
220  multicastDelegate._invocationCount = (IntPtr)invocationCount;
221  return multicastDelegate;
222  }
223 
224  [SecurityCritical]
225  internal MulticastDelegate NewMulticastDelegate(object[] invocationList, int invocationCount)
226  {
227  return NewMulticastDelegate(invocationList, invocationCount, thisIsMultiCastAlready: false);
228  }
229 
230  [SecurityCritical]
231  internal void StoreDynamicMethod(MethodInfo dynamicMethod)
232  {
233  if (_invocationCount != (IntPtr)0)
234  {
235  MulticastDelegate multicastDelegate = (MulticastDelegate)_invocationList;
236  multicastDelegate._methodBase = dynamicMethod;
237  }
238  else
239  {
240  _methodBase = dynamicMethod;
241  }
242  }
243 
250  [SecuritySafeCritical]
251  protected sealed override Delegate CombineImpl(Delegate follow)
252  {
253  if ((object)follow == null)
254  {
255  return this;
256  }
257  if (!Delegate.InternalEqualTypes(this, follow))
258  {
259  throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));
260  }
261  MulticastDelegate multicastDelegate = (MulticastDelegate)follow;
262  int num = 1;
263  object[] array = multicastDelegate._invocationList as object[];
264  if (array != null)
265  {
266  num = (int)multicastDelegate._invocationCount;
267  }
268  object[] array2 = _invocationList as object[];
269  int num2;
270  object[] array3;
271  if (array2 == null)
272  {
273  num2 = 1 + num;
274  array3 = new object[num2];
275  array3[0] = this;
276  if (array == null)
277  {
278  array3[1] = multicastDelegate;
279  }
280  else
281  {
282  for (int i = 0; i < num; i++)
283  {
284  array3[1 + i] = array[i];
285  }
286  }
287  return NewMulticastDelegate(array3, num2);
288  }
289  int num3 = (int)_invocationCount;
290  num2 = num3 + num;
291  array3 = null;
292  if (num2 <= array2.Length)
293  {
294  array3 = array2;
295  if (array == null)
296  {
297  if (!TrySetSlot(array3, num3, multicastDelegate))
298  {
299  array3 = null;
300  }
301  }
302  else
303  {
304  for (int j = 0; j < num; j++)
305  {
306  if (!TrySetSlot(array3, num3 + j, array[j]))
307  {
308  array3 = null;
309  break;
310  }
311  }
312  }
313  }
314  if (array3 == null)
315  {
316  int num4;
317  for (num4 = array2.Length; num4 < num2; num4 *= 2)
318  {
319  }
320  array3 = new object[num4];
321  for (int k = 0; k < num3; k++)
322  {
323  array3[k] = array2[k];
324  }
325  if (array == null)
326  {
327  array3[num3] = multicastDelegate;
328  }
329  else
330  {
331  for (int l = 0; l < num; l++)
332  {
333  array3[num3 + l] = array[l];
334  }
335  }
336  }
337  return NewMulticastDelegate(array3, num2, thisIsMultiCastAlready: true);
338  }
339 
340  [SecurityCritical]
341  private object[] DeleteFromInvocationList(object[] invocationList, int invocationCount, int deleteIndex, int deleteCount)
342  {
343  object[] array = _invocationList as object[];
344  int num = array.Length;
345  while (num / 2 >= invocationCount - deleteCount)
346  {
347  num /= 2;
348  }
349  object[] array2 = new object[num];
350  for (int i = 0; i < deleteIndex; i++)
351  {
352  array2[i] = invocationList[i];
353  }
354  for (int j = deleteIndex + deleteCount; j < invocationCount; j++)
355  {
356  array2[j - deleteCount] = invocationList[j];
357  }
358  return array2;
359  }
360 
361  private bool EqualInvocationLists(object[] a, object[] b, int start, int count)
362  {
363  for (int i = 0; i < count; i++)
364  {
365  if (!a[start + i].Equals(b[i]))
366  {
367  return false;
368  }
369  }
370  return true;
371  }
372 
377  [SecuritySafeCritical]
378  protected sealed override Delegate RemoveImpl(Delegate value)
379  {
380  MulticastDelegate multicastDelegate = value as MulticastDelegate;
381  if ((object)multicastDelegate == null)
382  {
383  return this;
384  }
385  if (!(multicastDelegate._invocationList is object[]))
386  {
387  object[] array = _invocationList as object[];
388  if (array == null)
389  {
390  if (Equals(value))
391  {
392  return null;
393  }
394  }
395  else
396  {
397  int num = (int)_invocationCount;
398  int num2 = num;
399  while (--num2 >= 0)
400  {
401  if (value.Equals(array[num2]))
402  {
403  if (num == 2)
404  {
405  return (Delegate)array[1 - num2];
406  }
407  object[] invocationList = DeleteFromInvocationList(array, num, num2, 1);
408  return NewMulticastDelegate(invocationList, num - 1, thisIsMultiCastAlready: true);
409  }
410  }
411  }
412  }
413  else
414  {
415  object[] array2 = _invocationList as object[];
416  if (array2 != null)
417  {
418  int num3 = (int)_invocationCount;
419  int num4 = (int)multicastDelegate._invocationCount;
420  for (int num5 = num3 - num4; num5 >= 0; num5--)
421  {
422  if (EqualInvocationLists(array2, multicastDelegate._invocationList as object[], num5, num4))
423  {
424  if (num3 - num4 == 0)
425  {
426  return null;
427  }
428  if (num3 - num4 == 1)
429  {
430  return (Delegate)array2[(num5 == 0) ? (num3 - 1) : 0];
431  }
432  object[] invocationList2 = DeleteFromInvocationList(array2, num3, num5, num4);
433  return NewMulticastDelegate(invocationList2, num3 - num4, thisIsMultiCastAlready: true);
434  }
435  }
436  }
437  }
438  return this;
439  }
440 
444  [SecuritySafeCritical]
445  [__DynamicallyInvokable]
446  public sealed override Delegate[] GetInvocationList()
447  {
448  object[] array = _invocationList as object[];
449  Delegate[] array2;
450  if (array == null)
451  {
452  array2 = new Delegate[1]
453  {
454  this
455  };
456  }
457  else
458  {
459  int num = (int)_invocationCount;
460  array2 = new Delegate[num];
461  for (int i = 0; i < num; i++)
462  {
463  array2[i] = (Delegate)array[i];
464  }
465  }
466  return array2;
467  }
468 
475  [__DynamicallyInvokable]
477  {
478  return d1?.Equals(d2) ?? ((object)d2 == null);
479  }
480 
487  [__DynamicallyInvokable]
489  {
490  if ((object)d1 == null)
491  {
492  return (object)d2 != null;
493  }
494  return !d1.Equals(d2);
495  }
496 
500  [SecuritySafeCritical]
501  [__DynamicallyInvokable]
502  public sealed override int GetHashCode()
503  {
504  if (IsUnmanagedFunctionPtr())
505  {
506  return ValueType.GetHashCodeOfPtr(_methodPtr) ^ ValueType.GetHashCodeOfPtr(_methodPtrAux);
507  }
508  object[] array = _invocationList as object[];
509  if (array == null)
510  {
511  return base.GetHashCode();
512  }
513  int num = 0;
514  for (int i = 0; i < (int)_invocationCount; i++)
515  {
516  num = num * 33 + array[i].GetHashCode();
517  }
518  return num;
519  }
520 
521  [SecuritySafeCritical]
522  internal override object GetTarget()
523  {
524  if (_invocationCount != (IntPtr)0)
525  {
526  if (InvocationListLogicallyNull())
527  {
528  return null;
529  }
530  object[] array = _invocationList as object[];
531  if (array != null)
532  {
533  int num = (int)_invocationCount;
534  return ((Delegate)array[num - 1]).GetTarget();
535  }
536  Delegate @delegate = _invocationList as Delegate;
537  if ((object)@delegate != null)
538  {
539  return @delegate.GetTarget();
540  }
541  }
542  return base.GetTarget();
543  }
544 
547  [SecuritySafeCritical]
548  protected override MethodInfo GetMethodImpl()
549  {
550  if (_invocationCount != (IntPtr)0 && _invocationList != null)
551  {
552  object[] array = _invocationList as object[];
553  if (array != null)
554  {
555  int num = (int)_invocationCount - 1;
556  return ((Delegate)array[num]).Method;
557  }
558  MulticastDelegate multicastDelegate = _invocationList as MulticastDelegate;
559  if ((object)multicastDelegate != null)
560  {
561  return multicastDelegate.GetMethodImpl();
562  }
563  }
564  else if (IsUnmanagedFunctionPtr())
565  {
566  if (_methodBase == null || !(_methodBase is MethodInfo))
567  {
568  IRuntimeMethodInfo runtimeMethodInfo = FindMethodHandle();
569  RuntimeType runtimeType = RuntimeMethodHandle.GetDeclaringType(runtimeMethodInfo);
570  if (RuntimeTypeHandle.IsGenericTypeDefinition(runtimeType) || RuntimeTypeHandle.HasInstantiation(runtimeType))
571  {
572  RuntimeType runtimeType2 = GetType() as RuntimeType;
573  runtimeType = runtimeType2;
574  }
575  _methodBase = (MethodInfo)RuntimeType.GetMethodBase(runtimeType, runtimeMethodInfo);
576  }
577  return (MethodInfo)_methodBase;
578  }
579  return base.GetMethodImpl();
580  }
581 
582  [DebuggerNonUserCode]
583  private void ThrowNullThisInDelegateToInstance()
584  {
585  throw new ArgumentException(Environment.GetResourceString("Arg_DlgtNullInst"));
586  }
587 
588  [SecurityCritical]
589  [DebuggerNonUserCode]
590  private void CtorClosed(object target, IntPtr methodPtr)
591  {
592  if (target == null)
593  {
594  ThrowNullThisInDelegateToInstance();
595  }
596  _target = target;
597  _methodPtr = methodPtr;
598  }
599 
600  [SecurityCritical]
601  [DebuggerNonUserCode]
602  private void CtorClosedStatic(object target, IntPtr methodPtr)
603  {
604  _target = target;
605  _methodPtr = methodPtr;
606  }
607 
608  [SecurityCritical]
609  [DebuggerNonUserCode]
610  private void CtorRTClosed(object target, IntPtr methodPtr)
611  {
612  _target = target;
613  _methodPtr = AdjustTarget(target, methodPtr);
614  }
615 
616  [SecurityCritical]
617  [DebuggerNonUserCode]
618  private void CtorOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk)
619  {
620  _target = this;
621  _methodPtr = shuffleThunk;
622  _methodPtrAux = methodPtr;
623  }
624 
625  [SecurityCritical]
626  [DebuggerNonUserCode]
627  private void CtorSecureClosed(object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod)
628  {
629  MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
630  multicastDelegate.CtorClosed(target, methodPtr);
631  _invocationList = multicastDelegate;
632  _target = this;
633  _methodPtr = callThunk;
634  _methodPtrAux = creatorMethod;
635  _invocationCount = GetInvokeMethod();
636  }
637 
638  [SecurityCritical]
639  [DebuggerNonUserCode]
640  private void CtorSecureClosedStatic(object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod)
641  {
642  MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
643  multicastDelegate.CtorClosedStatic(target, methodPtr);
644  _invocationList = multicastDelegate;
645  _target = this;
646  _methodPtr = callThunk;
647  _methodPtrAux = creatorMethod;
648  _invocationCount = GetInvokeMethod();
649  }
650 
651  [SecurityCritical]
652  [DebuggerNonUserCode]
653  private void CtorSecureRTClosed(object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod)
654  {
655  MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
656  multicastDelegate.CtorRTClosed(target, methodPtr);
657  _invocationList = multicastDelegate;
658  _target = this;
659  _methodPtr = callThunk;
660  _methodPtrAux = creatorMethod;
661  _invocationCount = GetInvokeMethod();
662  }
663 
664  [SecurityCritical]
665  [DebuggerNonUserCode]
666  private void CtorSecureOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr creatorMethod)
667  {
668  MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
669  multicastDelegate.CtorOpened(target, methodPtr, shuffleThunk);
670  _invocationList = multicastDelegate;
671  _target = this;
672  _methodPtr = callThunk;
673  _methodPtrAux = creatorMethod;
674  _invocationCount = GetInvokeMethod();
675  }
676 
677  [SecurityCritical]
678  [DebuggerNonUserCode]
679  private void CtorVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk)
680  {
681  _target = this;
682  _methodPtr = shuffleThunk;
683  _methodPtrAux = GetCallStub(methodPtr);
684  }
685 
686  [SecurityCritical]
687  [DebuggerNonUserCode]
688  private void CtorSecureVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr creatorMethod)
689  {
690  MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
691  multicastDelegate.CtorVirtualDispatch(target, methodPtr, shuffleThunk);
692  _invocationList = multicastDelegate;
693  _target = this;
694  _methodPtr = callThunk;
695  _methodPtrAux = creatorMethod;
696  _invocationCount = GetInvokeMethod();
697  }
698 
699  [SecurityCritical]
700  [DebuggerNonUserCode]
701  private void CtorCollectibleClosedStatic(object target, IntPtr methodPtr, IntPtr gchandle)
702  {
703  _target = target;
704  _methodPtr = methodPtr;
705  _methodBase = GCHandle.InternalGet(gchandle);
706  }
707 
708  [SecurityCritical]
709  [DebuggerNonUserCode]
710  private void CtorCollectibleOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle)
711  {
712  _target = this;
713  _methodPtr = shuffleThunk;
714  _methodPtrAux = methodPtr;
715  _methodBase = GCHandle.InternalGet(gchandle);
716  }
717 
718  [SecurityCritical]
719  [DebuggerNonUserCode]
720  private void CtorCollectibleVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle)
721  {
722  _target = this;
723  _methodPtr = shuffleThunk;
724  _methodPtrAux = GetCallStub(methodPtr);
725  _methodBase = GCHandle.InternalGet(gchandle);
726  }
727  }
728 }
override MethodInfo GetMethodImpl()
Returns a static method represented by the current T:System.MulticastDelegate.
MulticastDelegate(Type target, string method)
Initializes a new instance of the T:System.MulticastDelegate class.
sealed override int GetHashCode()
Returns the hash code for this instance.
Discovers the attributes of a method and provides access to method metadata.
Definition: MethodInfo.cs:13
static bool operator==(MulticastDelegate d1, MulticastDelegate d2)
Determines whether two T:System.MulticastDelegate objects are equal.
Represents a multicast delegate; that is, a delegate that can have more than one element in its invoc...
Definition: __Canon.cs:3
object Target
Gets the class instance on which the current delegate invokes the instance method.
Definition: Delegate.cs:46
Represents a type using an internal metadata token.
static bool operator !=(MulticastDelegate d1, MulticastDelegate d2)
Determines whether two T:System.MulticastDelegate objects are not equal.
Describes the source and destination of a given serialized stream, and provides an additional caller-...
Provides information about, and means to manipulate, the current environment and platform....
Definition: Environment.cs:21
T:System.RuntimeMethodHandle is a handle to the internal metadata representation of a method.
override void GetObjectData(SerializationInfo info, StreamingContext context)
Populates a T:System.Runtime.Serialization.SerializationInfo object with all the data needed to seria...
static int CompareExchange(ref int location1, int value, int comparand)
Compares two 32-bit signed integers for equality and, if they are equal, replaces the first value.
A platform-specific type that is used to represent a pointer or a handle.
Definition: IntPtr.cs:14
Represents a delegate, which is a data structure that refers to a static method or to a class instanc...
Definition: Delegate.cs:15
Represents type declarations: class types, interface types, array types, value types,...
Definition: Type.cs:18
The exception thrown when an error occurs during serialization or deserialization.
Provides a way to access a managed object from unmanaged memory.
Definition: GCHandle.cs:10
Stores all the data needed to serialize or deserialize an object. This class cannot be inherited.
MethodInfo Method
Gets the method represented by the delegate.
Definition: Delegate.cs:34
The exception that is thrown when one of the arguments provided to a method is not valid.
sealed override Delegate CombineImpl(Delegate follow)
Combines this T:System.Delegate with the specified T:System.Delegate to form a new delegate.
Specifies that the class can be serialized.
sealed override bool Equals(object obj)
Determines whether this multicast delegate and the specified object are equal.
sealed override Delegate RemoveImpl(Delegate value)
Removes an element from the invocation list of this T:System.MulticastDelegate that is equal to the s...
sealed override Delegate [] GetInvocationList()
Returns the invocation list of this multicast delegate, in invocation order.
Delegate(object target, string method)
Initializes a delegate that invokes the specified instance method on the specified class instance.
Definition: Delegate.cs:62
Provides atomic operations for variables that are shared by multiple threads.
Definition: Interlocked.cs:10
Provides the base class for value types.
Definition: ValueType.cs:12
MulticastDelegate(object target, string method)
Initializes a new instance of the T:System.MulticastDelegate class.
Attribute can be applied to a delegate.