Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / clr / src / BCL / System / MulticastDelegate.cs / 1 / MulticastDelegate.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
namespace System
{
using System;
using System.Reflection;
using System.Runtime.Serialization;
[Serializable()]
[System.Runtime.InteropServices.ComVisible(true)]
public abstract class MulticastDelegate : Delegate
{
private Object _invocationList;
private IntPtr _invocationCount;
// This constructor is called from the class generated by the
// compiler generated code (This must match the constructor
// in Delegate
protected MulticastDelegate(Object target, String method) : base(target, method)
{
}
// This constructor is called from a class to generate a
// delegate based upon a static method name and the Type object
// for the class defining the method.
protected MulticastDelegate(Type target, String method) : base(target, method)
{
}
internal bool IsUnmanagedFunctionPtr()
{
return (_invocationCount == (IntPtr)(-1));
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
int targetIndex = 0;
Object[] invocationList = _invocationList as Object[];
if (invocationList == null)
{
MethodInfo method = Method;
// if it is a delegate over a DynamicMethod or an unmanaged function pointer, throw
if (method is System.Reflection.Emit.DynamicMethod || method is System.Reflection.Emit.DynamicMethod.RTDynamicMethod || IsUnmanagedFunctionPtr())
throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
// We can't deal with secure delegates either.
if (_invocationList != null && !_invocationCount.IsNull())
throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
DelegateSerializationHolder.GetDelegateSerializationInfo(info, this.GetType(), Target, method, targetIndex);
}
else
{
DelegateSerializationHolder.DelegateEntry nextDe = null;
int invocationCount = (int)_invocationCount;
for (int i = invocationCount; --i >= 0; )
{
MulticastDelegate d = (MulticastDelegate)invocationList[i];
MethodInfo method = d.Method;
if (method is System.Reflection.Emit.DynamicMethod || method is System.Reflection.Emit.DynamicMethod.RTDynamicMethod || IsUnmanagedFunctionPtr())
continue;
// We can't deal with secure delegates either.
if (d._invocationList != null && !d._invocationCount.IsNull())
continue;
DelegateSerializationHolder.DelegateEntry de = DelegateSerializationHolder.GetDelegateSerializationInfo(info, d.GetType(), d.Target, method, targetIndex++);
if (nextDe != null)
nextDe.Entry = de;
nextDe = de;
}
// if nothing was serialized it is a delegate over a DynamicMethod, so just throw
if (nextDe == null)
throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
}
}
// 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 (obj == null || !InternalEqualTypes(this, obj))
return false;
MulticastDelegate d = obj as MulticastDelegate;
if (d == null)
return false;
if (_invocationCount != (IntPtr)0)
{
// there are 4 kind of delegate kinds that fall into this bucket
// 1- Multicast (_invocationList is Object[])
// 2- Secure (_invocationList is Delegate)
// 3- Unmanaged FntPtr (_invocationList == null)
// 4- Open virtual (_invocationCount == MethodDesc of target)
if (_invocationList == null)
{
if (IsUnmanagedFunctionPtr())
{
if (!d.IsUnmanagedFunctionPtr())
return false;
#if IA64
// For unmanaged delegates, methodPtr and methodPtrAux
// will always be unique.
return Delegate.CompareUnmanagedFunctionPtrs(this, d);
#else
if (_methodPtr != d._methodPtr)
return false;
if (GetUnmanagedCallSite() != d.GetUnmanagedCallSite())
return false;
return true;
#endif
}
return base.Equals(obj);
}
else
{
if ((_invocationList as Delegate) != null)
{
// this is a secure delegate so we need to unwrap and check the inner one
return _invocationList.Equals(obj);
}
else
{
BCLDebug.Assert((_invocationList as Object[]) != null, "empty invocation list on multicast delegate");
return InvocationListEquals(d);
}
}
}
else
{
// among the several kind of delegates falling into this bucket one has got a non
// empty _invocationList (open static with special sig)
// to be equals we need to check that _invocationList matches (both null is fine)
// and call the base.Equals()
if (_invocationList != null)
{
if (!_invocationList.Equals(d._invocationList))
return false;
return base.Equals(d);
}
// now we know 'this' is not a special one, so we can work out what the other is
if (d._invocationList != null || d._invocationCount != (IntPtr)0)
{
if ((d._invocationList as Delegate) != null)
// this is a secure delegate so we need to unwrap and check the inner one
return (d._invocationList as Delegate).Equals(this);
return false;
}
// now we can call on the base
return base.Equals(d);
}
}
// Recursive function which will check for equality of the invocation list.
private bool InvocationListEquals(MulticastDelegate d)
{
BCLDebug.Assert(d != null && (_invocationList as Object[]) != null, "bogus delegate in multicast list comparison");
Object[] invocationList = _invocationList as Object[];
if (d._invocationCount != _invocationCount)
return false;
int invocationCount = (int)_invocationCount;
for (int i = 0; i < invocationCount; i++)
{
Delegate dd = (Delegate)invocationList[i];
Object[] dInvocationList = d._invocationList as Object[];
if (!dd.Equals(dInvocationList[i]))
return false;
}
return true;
}
private bool TrySetSlot(Object[] a, int index, Object o)
{
if (a[index] == null && System.Threading.Interlocked.CompareExchange(ref a[index], o, null) == null)
return true;
// The slot may be already set because we have added and removed the same method before.
// Optimize this case, because it's cheaper than copying the array.
if (a[index] != null)
{
MulticastDelegate d = (MulticastDelegate)o;
MulticastDelegate dd = (MulticastDelegate)a[index];
if (dd._methodPtr == d._methodPtr &&
dd._target == d._target &&
dd._methodPtrAux == d._methodPtrAux)
{
return true;
}
}
return false;
}
internal MulticastDelegate NewMulticastDelegate(Object[] invocationList, int invocationCount, bool thisIsMultiCastAlready)
{
// First, allocate a new multicast delegate just like this one, i.e. same type as the this object
MulticastDelegate result = (MulticastDelegate)InternalAllocLike(this);
// Performance optimization - if this already points to a true multicast delegate,
// copy _methodPtr and _methodPtrAux fields rather than calling into the EE to get them
if (thisIsMultiCastAlready)
{
result._methodPtr = this._methodPtr;
result._methodPtrAux = this._methodPtrAux;
}
else
{
result._methodPtr = GetMulticastInvoke();
result._methodPtrAux = GetInvokeMethod();
}
result._target = result;
result._invocationList = invocationList;
result._invocationCount = (IntPtr)invocationCount;
return result;
}
internal MulticastDelegate NewMulticastDelegate(Object[] invocationList, int invocationCount)
{
return NewMulticastDelegate(invocationList, invocationCount, false);
}
internal void StoreDynamicMethod(MethodInfo dynamicMethod)
{
if (_invocationCount != (IntPtr)0)
{
BCLDebug.Assert(!IsUnmanagedFunctionPtr(), "dynamic method and unmanaged fntptr delegate combined");
// must be a secure one, unwrap and save
MulticastDelegate d = (MulticastDelegate)_invocationList;
d._methodBase = dynamicMethod;
}
else
_methodBase = dynamicMethod;
}
// This method will combine this delegate with the passed delegate
// to form a new delegate.
protected override sealed Delegate CombineImpl(Delegate follow)
{
if ((Object)follow == null) // cast to object for a more efficient test
return this;
// Verify that the types are the same...
if (!InternalEqualTypes(this, follow))
throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));
MulticastDelegate dFollow = (MulticastDelegate)follow;
Object[] resultList;
int followCount = 1;
Object[] followList = dFollow._invocationList as Object[];
if (followList != null)
followCount = (int)dFollow._invocationCount;
int resultCount;
Object[] invocationList = _invocationList as Object[];
if (invocationList == null)
{
resultCount = 1 + followCount;
resultList = new Object[resultCount];
resultList[0] = this;
if (followList == null)
{
resultList[1] = dFollow;
}
else
{
for (int i = 0; i < followCount; i++)
resultList[1 + i] = followList[i];
}
return NewMulticastDelegate(resultList, resultCount);
}
else
{
int invocationCount = (int)_invocationCount;
resultCount = invocationCount + followCount;
resultList = null;
if (resultCount <= invocationList.Length)
{
resultList = invocationList;
if (followList == null)
{
if (!TrySetSlot(resultList, invocationCount, dFollow))
resultList = null;
}
else
{
for (int i = 0; i < followCount; i++)
{
if (!TrySetSlot(resultList, invocationCount + i, followList[i]))
{
resultList = null;
break;
}
}
}
}
if (resultList == null)
{
int allocCount = invocationList.Length;
while (allocCount < resultCount)
allocCount *= 2;
resultList = new Object[allocCount];
for (int i = 0; i < invocationCount; i++)
resultList[i] = invocationList[i];
if (followList == null)
{
resultList[invocationCount] = dFollow;
}
else
{
for (int i = 0; i < followCount; i++)
resultList[invocationCount + i] = followList[i];
}
}
return NewMulticastDelegate(resultList, resultCount, true);
}
}
private Object[] DeleteFromInvocationList(Object[] invocationList, int invocationCount, int deleteIndex, int deleteCount)
{
Object[] thisInvocationList = _invocationList as Object[];
int allocCount = thisInvocationList.Length;
while (allocCount/2 >= invocationCount - deleteCount)
allocCount /= 2;
Object[] newInvocationList = new Object[allocCount];
for (int i = 0; i < deleteIndex; i++)
newInvocationList[i] = invocationList[i];
for (int i = deleteIndex + deleteCount; i < invocationCount; i++)
newInvocationList[i - deleteCount] = invocationList[i];
return newInvocationList;
}
private bool EqualInvocationLists(Object[] a, Object[] b, int start, int count)
{
for (int i = 0; i < count; i++)
{
if (!(a[start + i].Equals(b[i])))
return false;
}
return true;
}
// 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
//
MulticastDelegate v = value as MulticastDelegate;
if (v == null)
return this;
if (v._invocationList as Object[] == null)
{
Object[] invocationList = _invocationList as Object[];
if (invocationList == null)
{
// they are both not real Multicast
if (this.Equals(value))
return null;
}
else
{
int invocationCount = (int)_invocationCount;
for (int i = invocationCount; --i >= 0; )
{
if (value.Equals(invocationList[i]))
{
if (invocationCount == 2)
{
// Special case - only one value left, either at the beginning or the end
return (Delegate)invocationList[1-i];
}
else
{
Object[] list = DeleteFromInvocationList(invocationList, invocationCount, i, 1);
return NewMulticastDelegate(list, invocationCount-1, true);
}
}
}
}
}
else
{
Object[] invocationList = _invocationList as Object[];
if (invocationList != null) {
int invocationCount = (int)_invocationCount;
int vInvocationCount = (int)v._invocationCount;
for (int i = invocationCount - vInvocationCount; i >= 0; i--)
{
if (EqualInvocationLists(invocationList, v._invocationList as Object[], i, vInvocationCount))
{
if (invocationCount - vInvocationCount == 0)
{
// Special case - no values left
return null;
}
else if (invocationCount - vInvocationCount == 1)
{
// Special case - only one value left, either at the beginning or the end
return (Delegate)invocationList[i != 0 ? 0 : invocationCount-1];
}
else
{
Object[] list = DeleteFromInvocationList(invocationList, invocationCount, i, vInvocationCount);
return NewMulticastDelegate(list, invocationCount - vInvocationCount, true);
}
}
}
}
}
return this;
}
// This method returns the Invocation list of this multicast delegate.
public override sealed Delegate[] GetInvocationList()
{
Delegate[] del;
Object[] invocationList = _invocationList as Object[];
if (invocationList == null)
{
del = new Delegate[1];
del[0] = this;
}
else
{
// Create an array of delegate copies and each
// element into the array
int invocationCount = (int)_invocationCount;
del = new Delegate[invocationCount];
for (int i = 0; i < invocationCount; i++)
del[i] = (Delegate)invocationList[i];
}
return del;
}
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()
{
if (IsUnmanagedFunctionPtr())
return unchecked((int)((long)this._methodPtr));
Object[] invocationList = _invocationList as Object[];
if (invocationList == null)
{
return base.GetHashCode();
}
else
{
int hash = 0;
for (int i = 0; i < (int)_invocationCount; i++)
{
hash = hash*33 + invocationList[i].GetHashCode();
}
return hash;
}
}
internal override Object GetTarget()
{
if (_invocationCount != (IntPtr)0)
{
// _invocationCount != 0 we are in one of these cases:
// - Multicast -> return the target of the last delegate in the list
// - Secure delegate -> return the target of the inner delegate
// - unmanaged function pointer - return null
// - virtual open delegate - return base.GetTarget()
if (_invocationList == null)
{
// both open virtual and ftn pointer return null for the target
return null;
}
else
{
Object[] invocationList = _invocationList as Object[];
if (invocationList != null)
{
int invocationCount = (int)_invocationCount;
return ((Delegate)invocationList[invocationCount - 1]).GetTarget();
}
else
{
Delegate receiver = _invocationList as Delegate;
if (receiver != null)
return receiver.GetTarget();
}
}
}
return base.GetTarget();
}
protected override MethodInfo GetMethodImpl()
{
if (_invocationCount != (IntPtr)0 && _invocationList != null)
{
// multicast case
Object[] invocationList = _invocationList as Object[];
if (invocationList != null)
{
int index = (int)_invocationCount - 1;
return ((Delegate)invocationList[index]).Method;
}
else
{
// must be a secure delegate
return ((MulticastDelegate)_invocationList).GetMethodImpl();
}
}
return base.GetMethodImpl();
}
// this should help inlining
[System.Diagnostics.DebuggerNonUserCode]
private void ThrowNullThisInDelegateToInstance()
{
throw new ArgumentException(Environment.GetResourceString("Arg_DlgtNullInst"));
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorClosed(Object target, IntPtr methodPtr)
{
if (target == null)
ThrowNullThisInDelegateToInstance();
this._target = target;
this._methodPtr = methodPtr;
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorClosedStatic(Object target, IntPtr methodPtr)
{
this._target = target;
this._methodPtr = methodPtr;
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorRTClosed(Object target, IntPtr methodPtr)
{
this._target = target;
this._methodPtr = AdjustTarget(target, methodPtr);
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorOpened(Object target, IntPtr methodPtr, IntPtr shuffleThunk)
{
this._target = this;
this._methodPtr = shuffleThunk;
this._methodPtrAux = methodPtr;
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorSecureClosed(Object target, IntPtr methodPtr, IntPtr callThunk, IntPtr assembly)
{
MulticastDelegate realDelegate = (MulticastDelegate)Delegate.InternalAlloc(Type.GetTypeHandle(this));
realDelegate.CtorClosed(target, methodPtr);
this._invocationList = realDelegate;
this._target = this;
this._methodPtr = callThunk;
this._methodPtrAux = assembly;
this._invocationCount = GetInvokeMethod();
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorSecureClosedStatic(Object target, IntPtr methodPtr, IntPtr callThunk, IntPtr assembly)
{
MulticastDelegate realDelegate = (MulticastDelegate)Delegate.InternalAlloc(Type.GetTypeHandle(this));
realDelegate.CtorClosedStatic(target, methodPtr);
this._invocationList = realDelegate;
this._target = this;
this._methodPtr = callThunk;
this._methodPtrAux = assembly;
this._invocationCount = GetInvokeMethod();
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorSecureRTClosed(Object target, IntPtr methodPtr, IntPtr callThunk, IntPtr assembly)
{
MulticastDelegate realDelegate = Delegate.InternalAlloc(Type.GetTypeHandle(this));
realDelegate.CtorRTClosed(target, methodPtr);
this._invocationList = realDelegate;
this._target = this;
this._methodPtr = callThunk;
this._methodPtrAux = assembly;
this._invocationCount = GetInvokeMethod();
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorSecureOpened(Object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr assembly)
{
MulticastDelegate realDelegate = Delegate.InternalAlloc(Type.GetTypeHandle(this));
realDelegate.CtorOpened(target, methodPtr, shuffleThunk);
this._invocationList = realDelegate;
this._target = this;
this._methodPtr = callThunk;
this._methodPtrAux = assembly;
this._invocationCount = GetInvokeMethod();
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorVirtualDispatch(Object target, IntPtr methodPtr, IntPtr shuffleThunk)
{
this._target = this;
this._methodPtr = shuffleThunk;
this._methodPtrAux = GetCallStub(methodPtr);
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorSecureVirtualDispatch(Object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr assembly)
{
MulticastDelegate realDelegate = Delegate.InternalAlloc(Type.GetTypeHandle(this));
realDelegate.CtorVirtualDispatch(target, methodPtr, shuffleThunk);
this._invocationList = realDelegate;
this._target = this;
this._methodPtr = callThunk;
this._methodPtrAux = assembly;
this._invocationCount = GetInvokeMethod();
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
namespace System
{
using System;
using System.Reflection;
using System.Runtime.Serialization;
[Serializable()]
[System.Runtime.InteropServices.ComVisible(true)]
public abstract class MulticastDelegate : Delegate
{
private Object _invocationList;
private IntPtr _invocationCount;
// This constructor is called from the class generated by the
// compiler generated code (This must match the constructor
// in Delegate
protected MulticastDelegate(Object target, String method) : base(target, method)
{
}
// This constructor is called from a class to generate a
// delegate based upon a static method name and the Type object
// for the class defining the method.
protected MulticastDelegate(Type target, String method) : base(target, method)
{
}
internal bool IsUnmanagedFunctionPtr()
{
return (_invocationCount == (IntPtr)(-1));
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
int targetIndex = 0;
Object[] invocationList = _invocationList as Object[];
if (invocationList == null)
{
MethodInfo method = Method;
// if it is a delegate over a DynamicMethod or an unmanaged function pointer, throw
if (method is System.Reflection.Emit.DynamicMethod || method is System.Reflection.Emit.DynamicMethod.RTDynamicMethod || IsUnmanagedFunctionPtr())
throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
// We can't deal with secure delegates either.
if (_invocationList != null && !_invocationCount.IsNull())
throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
DelegateSerializationHolder.GetDelegateSerializationInfo(info, this.GetType(), Target, method, targetIndex);
}
else
{
DelegateSerializationHolder.DelegateEntry nextDe = null;
int invocationCount = (int)_invocationCount;
for (int i = invocationCount; --i >= 0; )
{
MulticastDelegate d = (MulticastDelegate)invocationList[i];
MethodInfo method = d.Method;
if (method is System.Reflection.Emit.DynamicMethod || method is System.Reflection.Emit.DynamicMethod.RTDynamicMethod || IsUnmanagedFunctionPtr())
continue;
// We can't deal with secure delegates either.
if (d._invocationList != null && !d._invocationCount.IsNull())
continue;
DelegateSerializationHolder.DelegateEntry de = DelegateSerializationHolder.GetDelegateSerializationInfo(info, d.GetType(), d.Target, method, targetIndex++);
if (nextDe != null)
nextDe.Entry = de;
nextDe = de;
}
// if nothing was serialized it is a delegate over a DynamicMethod, so just throw
if (nextDe == null)
throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
}
}
// 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 (obj == null || !InternalEqualTypes(this, obj))
return false;
MulticastDelegate d = obj as MulticastDelegate;
if (d == null)
return false;
if (_invocationCount != (IntPtr)0)
{
// there are 4 kind of delegate kinds that fall into this bucket
// 1- Multicast (_invocationList is Object[])
// 2- Secure (_invocationList is Delegate)
// 3- Unmanaged FntPtr (_invocationList == null)
// 4- Open virtual (_invocationCount == MethodDesc of target)
if (_invocationList == null)
{
if (IsUnmanagedFunctionPtr())
{
if (!d.IsUnmanagedFunctionPtr())
return false;
#if IA64
// For unmanaged delegates, methodPtr and methodPtrAux
// will always be unique.
return Delegate.CompareUnmanagedFunctionPtrs(this, d);
#else
if (_methodPtr != d._methodPtr)
return false;
if (GetUnmanagedCallSite() != d.GetUnmanagedCallSite())
return false;
return true;
#endif
}
return base.Equals(obj);
}
else
{
if ((_invocationList as Delegate) != null)
{
// this is a secure delegate so we need to unwrap and check the inner one
return _invocationList.Equals(obj);
}
else
{
BCLDebug.Assert((_invocationList as Object[]) != null, "empty invocation list on multicast delegate");
return InvocationListEquals(d);
}
}
}
else
{
// among the several kind of delegates falling into this bucket one has got a non
// empty _invocationList (open static with special sig)
// to be equals we need to check that _invocationList matches (both null is fine)
// and call the base.Equals()
if (_invocationList != null)
{
if (!_invocationList.Equals(d._invocationList))
return false;
return base.Equals(d);
}
// now we know 'this' is not a special one, so we can work out what the other is
if (d._invocationList != null || d._invocationCount != (IntPtr)0)
{
if ((d._invocationList as Delegate) != null)
// this is a secure delegate so we need to unwrap and check the inner one
return (d._invocationList as Delegate).Equals(this);
return false;
}
// now we can call on the base
return base.Equals(d);
}
}
// Recursive function which will check for equality of the invocation list.
private bool InvocationListEquals(MulticastDelegate d)
{
BCLDebug.Assert(d != null && (_invocationList as Object[]) != null, "bogus delegate in multicast list comparison");
Object[] invocationList = _invocationList as Object[];
if (d._invocationCount != _invocationCount)
return false;
int invocationCount = (int)_invocationCount;
for (int i = 0; i < invocationCount; i++)
{
Delegate dd = (Delegate)invocationList[i];
Object[] dInvocationList = d._invocationList as Object[];
if (!dd.Equals(dInvocationList[i]))
return false;
}
return true;
}
private bool TrySetSlot(Object[] a, int index, Object o)
{
if (a[index] == null && System.Threading.Interlocked.CompareExchange(ref a[index], o, null) == null)
return true;
// The slot may be already set because we have added and removed the same method before.
// Optimize this case, because it's cheaper than copying the array.
if (a[index] != null)
{
MulticastDelegate d = (MulticastDelegate)o;
MulticastDelegate dd = (MulticastDelegate)a[index];
if (dd._methodPtr == d._methodPtr &&
dd._target == d._target &&
dd._methodPtrAux == d._methodPtrAux)
{
return true;
}
}
return false;
}
internal MulticastDelegate NewMulticastDelegate(Object[] invocationList, int invocationCount, bool thisIsMultiCastAlready)
{
// First, allocate a new multicast delegate just like this one, i.e. same type as the this object
MulticastDelegate result = (MulticastDelegate)InternalAllocLike(this);
// Performance optimization - if this already points to a true multicast delegate,
// copy _methodPtr and _methodPtrAux fields rather than calling into the EE to get them
if (thisIsMultiCastAlready)
{
result._methodPtr = this._methodPtr;
result._methodPtrAux = this._methodPtrAux;
}
else
{
result._methodPtr = GetMulticastInvoke();
result._methodPtrAux = GetInvokeMethod();
}
result._target = result;
result._invocationList = invocationList;
result._invocationCount = (IntPtr)invocationCount;
return result;
}
internal MulticastDelegate NewMulticastDelegate(Object[] invocationList, int invocationCount)
{
return NewMulticastDelegate(invocationList, invocationCount, false);
}
internal void StoreDynamicMethod(MethodInfo dynamicMethod)
{
if (_invocationCount != (IntPtr)0)
{
BCLDebug.Assert(!IsUnmanagedFunctionPtr(), "dynamic method and unmanaged fntptr delegate combined");
// must be a secure one, unwrap and save
MulticastDelegate d = (MulticastDelegate)_invocationList;
d._methodBase = dynamicMethod;
}
else
_methodBase = dynamicMethod;
}
// This method will combine this delegate with the passed delegate
// to form a new delegate.
protected override sealed Delegate CombineImpl(Delegate follow)
{
if ((Object)follow == null) // cast to object for a more efficient test
return this;
// Verify that the types are the same...
if (!InternalEqualTypes(this, follow))
throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));
MulticastDelegate dFollow = (MulticastDelegate)follow;
Object[] resultList;
int followCount = 1;
Object[] followList = dFollow._invocationList as Object[];
if (followList != null)
followCount = (int)dFollow._invocationCount;
int resultCount;
Object[] invocationList = _invocationList as Object[];
if (invocationList == null)
{
resultCount = 1 + followCount;
resultList = new Object[resultCount];
resultList[0] = this;
if (followList == null)
{
resultList[1] = dFollow;
}
else
{
for (int i = 0; i < followCount; i++)
resultList[1 + i] = followList[i];
}
return NewMulticastDelegate(resultList, resultCount);
}
else
{
int invocationCount = (int)_invocationCount;
resultCount = invocationCount + followCount;
resultList = null;
if (resultCount <= invocationList.Length)
{
resultList = invocationList;
if (followList == null)
{
if (!TrySetSlot(resultList, invocationCount, dFollow))
resultList = null;
}
else
{
for (int i = 0; i < followCount; i++)
{
if (!TrySetSlot(resultList, invocationCount + i, followList[i]))
{
resultList = null;
break;
}
}
}
}
if (resultList == null)
{
int allocCount = invocationList.Length;
while (allocCount < resultCount)
allocCount *= 2;
resultList = new Object[allocCount];
for (int i = 0; i < invocationCount; i++)
resultList[i] = invocationList[i];
if (followList == null)
{
resultList[invocationCount] = dFollow;
}
else
{
for (int i = 0; i < followCount; i++)
resultList[invocationCount + i] = followList[i];
}
}
return NewMulticastDelegate(resultList, resultCount, true);
}
}
private Object[] DeleteFromInvocationList(Object[] invocationList, int invocationCount, int deleteIndex, int deleteCount)
{
Object[] thisInvocationList = _invocationList as Object[];
int allocCount = thisInvocationList.Length;
while (allocCount/2 >= invocationCount - deleteCount)
allocCount /= 2;
Object[] newInvocationList = new Object[allocCount];
for (int i = 0; i < deleteIndex; i++)
newInvocationList[i] = invocationList[i];
for (int i = deleteIndex + deleteCount; i < invocationCount; i++)
newInvocationList[i - deleteCount] = invocationList[i];
return newInvocationList;
}
private bool EqualInvocationLists(Object[] a, Object[] b, int start, int count)
{
for (int i = 0; i < count; i++)
{
if (!(a[start + i].Equals(b[i])))
return false;
}
return true;
}
// 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
//
MulticastDelegate v = value as MulticastDelegate;
if (v == null)
return this;
if (v._invocationList as Object[] == null)
{
Object[] invocationList = _invocationList as Object[];
if (invocationList == null)
{
// they are both not real Multicast
if (this.Equals(value))
return null;
}
else
{
int invocationCount = (int)_invocationCount;
for (int i = invocationCount; --i >= 0; )
{
if (value.Equals(invocationList[i]))
{
if (invocationCount == 2)
{
// Special case - only one value left, either at the beginning or the end
return (Delegate)invocationList[1-i];
}
else
{
Object[] list = DeleteFromInvocationList(invocationList, invocationCount, i, 1);
return NewMulticastDelegate(list, invocationCount-1, true);
}
}
}
}
}
else
{
Object[] invocationList = _invocationList as Object[];
if (invocationList != null) {
int invocationCount = (int)_invocationCount;
int vInvocationCount = (int)v._invocationCount;
for (int i = invocationCount - vInvocationCount; i >= 0; i--)
{
if (EqualInvocationLists(invocationList, v._invocationList as Object[], i, vInvocationCount))
{
if (invocationCount - vInvocationCount == 0)
{
// Special case - no values left
return null;
}
else if (invocationCount - vInvocationCount == 1)
{
// Special case - only one value left, either at the beginning or the end
return (Delegate)invocationList[i != 0 ? 0 : invocationCount-1];
}
else
{
Object[] list = DeleteFromInvocationList(invocationList, invocationCount, i, vInvocationCount);
return NewMulticastDelegate(list, invocationCount - vInvocationCount, true);
}
}
}
}
}
return this;
}
// This method returns the Invocation list of this multicast delegate.
public override sealed Delegate[] GetInvocationList()
{
Delegate[] del;
Object[] invocationList = _invocationList as Object[];
if (invocationList == null)
{
del = new Delegate[1];
del[0] = this;
}
else
{
// Create an array of delegate copies and each
// element into the array
int invocationCount = (int)_invocationCount;
del = new Delegate[invocationCount];
for (int i = 0; i < invocationCount; i++)
del[i] = (Delegate)invocationList[i];
}
return del;
}
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()
{
if (IsUnmanagedFunctionPtr())
return unchecked((int)((long)this._methodPtr));
Object[] invocationList = _invocationList as Object[];
if (invocationList == null)
{
return base.GetHashCode();
}
else
{
int hash = 0;
for (int i = 0; i < (int)_invocationCount; i++)
{
hash = hash*33 + invocationList[i].GetHashCode();
}
return hash;
}
}
internal override Object GetTarget()
{
if (_invocationCount != (IntPtr)0)
{
// _invocationCount != 0 we are in one of these cases:
// - Multicast -> return the target of the last delegate in the list
// - Secure delegate -> return the target of the inner delegate
// - unmanaged function pointer - return null
// - virtual open delegate - return base.GetTarget()
if (_invocationList == null)
{
// both open virtual and ftn pointer return null for the target
return null;
}
else
{
Object[] invocationList = _invocationList as Object[];
if (invocationList != null)
{
int invocationCount = (int)_invocationCount;
return ((Delegate)invocationList[invocationCount - 1]).GetTarget();
}
else
{
Delegate receiver = _invocationList as Delegate;
if (receiver != null)
return receiver.GetTarget();
}
}
}
return base.GetTarget();
}
protected override MethodInfo GetMethodImpl()
{
if (_invocationCount != (IntPtr)0 && _invocationList != null)
{
// multicast case
Object[] invocationList = _invocationList as Object[];
if (invocationList != null)
{
int index = (int)_invocationCount - 1;
return ((Delegate)invocationList[index]).Method;
}
else
{
// must be a secure delegate
return ((MulticastDelegate)_invocationList).GetMethodImpl();
}
}
return base.GetMethodImpl();
}
// this should help inlining
[System.Diagnostics.DebuggerNonUserCode]
private void ThrowNullThisInDelegateToInstance()
{
throw new ArgumentException(Environment.GetResourceString("Arg_DlgtNullInst"));
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorClosed(Object target, IntPtr methodPtr)
{
if (target == null)
ThrowNullThisInDelegateToInstance();
this._target = target;
this._methodPtr = methodPtr;
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorClosedStatic(Object target, IntPtr methodPtr)
{
this._target = target;
this._methodPtr = methodPtr;
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorRTClosed(Object target, IntPtr methodPtr)
{
this._target = target;
this._methodPtr = AdjustTarget(target, methodPtr);
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorOpened(Object target, IntPtr methodPtr, IntPtr shuffleThunk)
{
this._target = this;
this._methodPtr = shuffleThunk;
this._methodPtrAux = methodPtr;
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorSecureClosed(Object target, IntPtr methodPtr, IntPtr callThunk, IntPtr assembly)
{
MulticastDelegate realDelegate = (MulticastDelegate)Delegate.InternalAlloc(Type.GetTypeHandle(this));
realDelegate.CtorClosed(target, methodPtr);
this._invocationList = realDelegate;
this._target = this;
this._methodPtr = callThunk;
this._methodPtrAux = assembly;
this._invocationCount = GetInvokeMethod();
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorSecureClosedStatic(Object target, IntPtr methodPtr, IntPtr callThunk, IntPtr assembly)
{
MulticastDelegate realDelegate = (MulticastDelegate)Delegate.InternalAlloc(Type.GetTypeHandle(this));
realDelegate.CtorClosedStatic(target, methodPtr);
this._invocationList = realDelegate;
this._target = this;
this._methodPtr = callThunk;
this._methodPtrAux = assembly;
this._invocationCount = GetInvokeMethod();
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorSecureRTClosed(Object target, IntPtr methodPtr, IntPtr callThunk, IntPtr assembly)
{
MulticastDelegate realDelegate = Delegate.InternalAlloc(Type.GetTypeHandle(this));
realDelegate.CtorRTClosed(target, methodPtr);
this._invocationList = realDelegate;
this._target = this;
this._methodPtr = callThunk;
this._methodPtrAux = assembly;
this._invocationCount = GetInvokeMethod();
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorSecureOpened(Object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr assembly)
{
MulticastDelegate realDelegate = Delegate.InternalAlloc(Type.GetTypeHandle(this));
realDelegate.CtorOpened(target, methodPtr, shuffleThunk);
this._invocationList = realDelegate;
this._target = this;
this._methodPtr = callThunk;
this._methodPtrAux = assembly;
this._invocationCount = GetInvokeMethod();
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorVirtualDispatch(Object target, IntPtr methodPtr, IntPtr shuffleThunk)
{
this._target = this;
this._methodPtr = shuffleThunk;
this._methodPtrAux = GetCallStub(methodPtr);
}
[System.Diagnostics.DebuggerNonUserCode]
private void CtorSecureVirtualDispatch(Object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr assembly)
{
MulticastDelegate realDelegate = Delegate.InternalAlloc(Type.GetTypeHandle(this));
realDelegate.CtorVirtualDispatch(target, methodPtr, shuffleThunk);
this._invocationList = realDelegate;
this._target = this;
this._methodPtr = callThunk;
this._methodPtrAux = assembly;
this._invocationCount = GetInvokeMethod();
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TextCollapsingProperties.cs
- TextFormattingConverter.cs
- ColorMap.cs
- XmlDataProvider.cs
- CustomAssemblyResolver.cs
- BmpBitmapEncoder.cs
- TabControl.cs
- SchemaNotation.cs
- ListMarkerLine.cs
- HtmlElementErrorEventArgs.cs
- InvariantComparer.cs
- HttpApplication.cs
- SessionStateUtil.cs
- TextParagraphProperties.cs
- ModelItemImpl.cs
- Crc32Helper.cs
- SamlAuthorityBinding.cs
- TraceData.cs
- WebBrowserUriTypeConverter.cs
- PenContext.cs
- DWriteFactory.cs
- CodeDOMUtility.cs
- ExceptionValidationRule.cs
- GridItemCollection.cs
- QilStrConcatenator.cs
- EdmMember.cs
- ToolStripDesigner.cs
- BindableAttribute.cs
- GZipStream.cs
- SQLByte.cs
- TripleDES.cs
- PackageRelationshipSelector.cs
- FixedTextContainer.cs
- HelpProvider.cs
- PropertyRecord.cs
- Thumb.cs
- SQLRoleProvider.cs
- MethodImplAttribute.cs
- ACE.cs
- CaseStatement.cs
- Nullable.cs
- FormsAuthentication.cs
- NativeRecognizer.cs
- FunctionQuery.cs
- Timer.cs
- Quaternion.cs
- DocumentGridPage.cs
- CodeCatchClause.cs
- XmlSchemas.cs
- ForceCopyBuildProvider.cs
- LogicalExpr.cs
- FormsAuthenticationUser.cs
- SafeEventLogWriteHandle.cs
- RequestDescription.cs
- FullTrustAssemblyCollection.cs
- DescendantOverDescendantQuery.cs
- DefaultAsyncDataDispatcher.cs
- ModelFunction.cs
- CompatibleComparer.cs
- ImageIndexConverter.cs
- EqualityComparer.cs
- JapaneseLunisolarCalendar.cs
- DiscoveryEndpointValidator.cs
- IconEditor.cs
- ApplicationTrust.cs
- ProviderConnectionPoint.cs
- ClientSettingsSection.cs
- DocumentPaginator.cs
- Socket.cs
- ILGenerator.cs
- EdmMember.cs
- ZipIOZip64EndOfCentralDirectoryBlock.cs
- FacetChecker.cs
- HttpCapabilitiesBase.cs
- ValuePatternIdentifiers.cs
- XmlSchemaSimpleContentExtension.cs
- PlatformNotSupportedException.cs
- ErrorFormatter.cs
- Pointer.cs
- ProcessingInstructionAction.cs
- PerformanceCounter.cs
- VisualBrush.cs
- ShutDownListener.cs
- HtmlGenericControl.cs
- AccessDataSourceView.cs
- XmlQueryCardinality.cs
- AbstractDataSvcMapFileLoader.cs
- HtmlElementCollection.cs
- SqlResolver.cs
- MobileControl.cs
- ServiceBusyException.cs
- RelationshipConstraintValidator.cs
- RegexStringValidator.cs
- DESCryptoServiceProvider.cs
- EntityDesignerDataSourceView.cs
- TreeViewDesigner.cs
- DesigntimeLicenseContextSerializer.cs
- AsymmetricKeyExchangeFormatter.cs
- PatternMatcher.cs
- ResourceProviderFactory.cs