// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== namespace System { using System; using System.Reflection; //| public abstract class MulticastDelegate : Delegate { // This is a pointer to a delegate that is logically the // delegate before this one. [System.Runtime.CompilerServices.RequiredByBartok] private MulticastDelegate _prev; internal MulticastDelegate Previous { get{return _prev;} set{_prev = value;} } // equals returns true IIF the delegate is not null and has the // same target, method and invocation list as this object //| public override sealed bool Equals(Object obj) { if (!base.Equals(obj)) return false; if (_prev != null) return _prev.InvocationListEquals(((MulticastDelegate) obj)._prev); else { // if we got here, "this" is a Multicast with only one listener. if (obj is MulticastDelegate) return ((MulticastDelegate)obj)._prev == null; else if (obj is Delegate) return true; else return false; } } // Recursive function which will check for equality of the invocation list. private bool InvocationListEquals(MulticastDelegate d) { if (!base.Equals(d)) return false; if (_prev == d._prev) return true; if (_prev == null) return (d._prev == null) ? true : false; return _prev.InvocationListEquals(d._prev); } // This method will combine this delegate with the passed delegate // to form a new delegate. //| protected override sealed Delegate CombineImpl(Delegate follow) { // Verify that the types are the same... if (this.GetType() != follow.GetType()) throw new ArgumentException("Arg_DlgtTypeMis"); // We always clone the delegate because this delegate is // not changed by combine and remove. We can safely tack // the follow delegate onto the end of the copy. MulticastDelegate d = (MulticastDelegate) ((MulticastDelegate) follow).MemberwiseClone(); MulticastDelegate root = d; while (d._prev != null) { d._prev = (MulticastDelegate) d._prev.MemberwiseClone(); d = d._prev; } d._prev = (MulticastDelegate) this; return root; } // This method currently looks backward on the invocation list // for an element that has Delegate based equality with value. (Doesn't // look at the invocation list.) If this is found we remove it from // this list and return a new delegate. If its not found a copy of the // current list is returned. //| protected override sealed Delegate RemoveImpl(Delegate value) { // There is a special case were we are removing using a delegate as // the value we need to check for this case // if (!(value is MulticastDelegate)) { if (base.Equals(value)) return _prev; return this; } // Look for the delegate... MulticastDelegate v = (MulticastDelegate) value; if (InternalEquals(v)) { int size = v.DelSize(); MulticastDelegate p = _prev; while (--size != 0) p = p._prev; return p; } MulticastDelegate d = (MulticastDelegate) this.MemberwiseClone(); MulticastDelegate root = d; while (d._prev != null && d._prev.InternalEquals(v) != true) { d._prev = (MulticastDelegate) d._prev.MemberwiseClone(); d = d._prev; } if (d._prev != null) { int size = v.DelSize(); MulticastDelegate p = d._prev._prev; while (--size != 0) p = p._prev; d._prev = p; } return root; } private int DelSize() { int i=0; MulticastDelegate d = this; while (d != null) { i++; d = d._prev; } return i; } // Stupid helper function to check equality based upon the super class. private bool InternalEquals(Delegate d) { if (!base.Equals(d)) return false; if (((MulticastDelegate) d)._prev != null) { if (_prev == null) return false; return _prev.InternalEquals(((MulticastDelegate) d)._prev); } return true; } // This method returns the Invocation list of this multicast delegate. //| public override sealed Delegate[] GetInvocationList() { int i = 0; MulticastDelegate p; // How big is the invocation list? for (p = this; p != null; p = p._prev) i++; // Create an array of delegate copies and each // element into the array (Need to reverse the order and make sure // we set the _prev to null. Delegate[] del = new Delegate[i]; for (p = this; p != null; p = p._prev) { del[--i] = (Delegate) p.MemberwiseClone(); ((MulticastDelegate) del[i])._prev = null; } return del; } /* private static bool operator equals(MulticastDelegate d1, MulticastDelegate d2) { if ((Object)d1 == null) return (Object)d2 == null; return d1.Equals(d2); }*/ //| public static bool operator ==(MulticastDelegate d1, MulticastDelegate d2) { if ((Object)d1 == null) return (Object)d2 == null; return d1.Equals(d2); } //| public static bool operator !=(MulticastDelegate d1, MulticastDelegate d2) { if ((Object)d1 == null) return (Object)d2 != null; return !d1.Equals(d2); } //| public override sealed int GetHashCode() { return base.GetHashCode(); } } }