/// <summary> /// Constructor. /// </summary> /// <param name="del">The parent delgate that this target came from.</param> /// <param name="target">The "target" of this delegate.</param> /// <param name="method">The method this delegate will call.</param> public ClrDelegateTarget(ClrDelegate del, ClrObject target, ClrMethod method) { if (method is null) { throw new ArgumentNullException(nameof(method)); } Parent = del; TargetObject = target; Method = method; }
/// <summary> /// Enumerates all delegate targets of this delegate. If called on a MulitcastDelegate, this will enumerate all /// targets that will be called when this delegate is invoked. If called on a non-MulticastDelegate, this will /// enumerate the value of GetDelegateTarget. /// </summary> /// <returns></returns> public IEnumerable <ClrDelegateTarget> EnumerateDelegateTargets() { ClrDelegateTarget?first = GetDelegateTarget(); if (first != null) { yield return(first); } // The call to GetDelegateMethod will validate that we are a valid object and a subclass of System.Delegate if (!Object.TryReadField("_invocationCount", out int count) || count == 0 || !Object.TryReadObjectField("_invocationList", out ClrObject invocationList) || !invocationList.IsArray) { yield break; } ClrArray invocationArray = invocationList.AsArray(); count = Math.Min(count, invocationArray.Length); ClrHeap heap = Object.Type !.Heap; UIntPtr[]? pointers = invocationArray.ReadValues <UIntPtr>(0, count); if (pointers is not null) { foreach (UIntPtr ptr in pointers) { if (ptr == UIntPtr.Zero) { continue; } ClrObject delegateObj = heap.GetObject(ptr.ToUInt64()); if (delegateObj.IsDelegate) { ClrDelegateTarget?delegateTarget = new ClrDelegate(delegateObj).GetDelegateTarget(); if (delegateTarget is not null) { yield return(delegateTarget); } } } } }