The Labs \ Source Viewer \ SSCLI \ System \ MulticastDelegate

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System
  16. {
  17.     using System;
  18.     using System.Reflection;
  19.     using System.Runtime.Serialization;
  20.    
  21.     [Serializable()]
  22.     [System.Runtime.InteropServices.ComVisible(true)]
  23.     public abstract class MulticastDelegate : Delegate
  24.     {
  25.         private object _invocationList;
  26.         private IntPtr _invocationCount;
  27.        
  28.         // This constructor is called from the class generated by the
  29.         // compiler generated code (This must match the constructor
  30.         // in Delegate
  31.         protected MulticastDelegate(object target, string method) : base(target, method)
  32.         {
  33.         }
  34.        
  35.         // This constructor is called from a class to generate a
  36.         // delegate based upon a static method name and the Type object
  37.         // for the class defining the method.
  38.         protected MulticastDelegate(Type target, string method) : base(target, method)
  39.         {
  40.         }
  41.        
  42.         internal bool IsUnmanagedFunctionPtr()
  43.         {
  44.             return (_invocationCount == (IntPtr)(-1));
  45.         }
  46.        
  47.         public override void GetObjectData(SerializationInfo info, StreamingContext context)
  48.         {
  49.             int targetIndex = 0;
  50.             object[] invocationList = _invocationList as object[];
  51.             if (invocationList == null) {
  52.                 MethodInfo method = Method;
  53.                 // if it is a delegate over a DynamicMethod or an unmanaged function pointer, throw
  54.                 if (method is System.Reflection.Emit.DynamicMethod || method is System.Reflection.Emit.DynamicMethod.RTDynamicMethod || IsUnmanagedFunctionPtr())
  55.                     throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
  56.                
  57.                 // We can't deal with secure delegates either.
  58.                 if (_invocationList != null && !_invocationCount.IsNull())
  59.                     throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
  60.                
  61.                 DelegateSerializationHolder.GetDelegateSerializationInfo(info, this.GetType(), Target, method, targetIndex);
  62.             }
  63.             else {
  64.                 DelegateSerializationHolder.DelegateEntry nextDe = null;
  65.                 int invocationCount = (int)_invocationCount;
  66.                 for (int i = invocationCount; --i >= 0;) {
  67.                     MulticastDelegate d = (MulticastDelegate)invocationList[i];
  68.                     MethodInfo method = d.Method;
  69.                     if (method is System.Reflection.Emit.DynamicMethod || method is System.Reflection.Emit.DynamicMethod.RTDynamicMethod || IsUnmanagedFunctionPtr())
  70.                         continue;
  71.                    
  72.                     // We can't deal with secure delegates either.
  73.                     if (d._invocationList != null && !d._invocationCount.IsNull())
  74.                         continue;
  75.                    
  76.                     DelegateSerializationHolder.DelegateEntry de = DelegateSerializationHolder.GetDelegateSerializationInfo(info, d.GetType(), d.Target, method, targetIndex++);
  77.                     if (nextDe != null)
  78.                         nextDe.Entry = de;
  79.                    
  80.                     nextDe = de;
  81.                 }
  82.                 // if nothing was serialized it is a delegate over a DynamicMethod, so just throw
  83.                 if (nextDe == null)
  84.                     throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
  85.             }
  86.         }
  87.        
  88.         // equals returns true IIF the delegate is not null and has the
  89.         // same target, method and invocation list as this object
  90.         public override sealed bool Equals(object obj)
  91.         {
  92.             if (obj == null || !InternalEqualTypes(this, obj))
  93.                 return false;
  94.             MulticastDelegate d = obj as MulticastDelegate;
  95.             if (d == null)
  96.                 return false;
  97.            
  98.             if (_invocationCount != (IntPtr)0) {
  99.                 // there are 4 kind of delegate kinds that fall into this bucket
  100.                 // 1- Multicast (_invocationList is Object[])
  101.                 // 2- Secure (_invocationList is Delegate)
  102.                 // 3- Unmanaged FntPtr (_invocationList == null)
  103.                 // 4- Open virtual (_invocationCount == MethodDesc of target)
  104.                
  105.                 if (_invocationList == null) {
  106.                     if (IsUnmanagedFunctionPtr()) {
  107.                         if (!d.IsUnmanagedFunctionPtr())
  108.                             return false;
  109.                        
  110.                        
  111.                         if (_methodPtr != d._methodPtr)
  112.                             return false;
  113.                        
  114.                         if (GetUnmanagedCallSite() != d.GetUnmanagedCallSite())
  115.                             return false;
  116.                        
  117.                         return true;
  118.                     }
  119.                     return base.Equals(obj);
  120.                 }
  121.                 else {
  122.                     if ((_invocationList as Delegate) != null) {
  123.                         // this is a secure delegate so we need to unwrap and check the inner one
  124.                         return _invocationList.Equals(obj);
  125.                     }
  126.                     else {
  127.                         BCLDebug.Assert((_invocationList as object[]) != null, "empty invocation list on multicast delegate");
  128.                         return InvocationListEquals(d);
  129.                     }
  130.                 }
  131.             }
  132.             else {
  133.                 // among the several kind of delegates falling into this bucket one has got a non
  134.                 // empty _invocationList (open static with special sig)
  135.                 // to be equals we need to check that _invocationList matches (both null is fine)
  136.                 // and call the base.Equals()
  137.                 if (_invocationList != null) {
  138.                     if (!_invocationList.Equals(d._invocationList))
  139.                         return false;
  140.                     return base.Equals(d);
  141.                 }
  142.                
  143.                 // now we know 'this' is not a special one, so we can work out what the other is
  144.                 if (d._invocationList != null || d._invocationCount != (IntPtr)0) {
  145.                     if ((d._invocationList as Delegate) != null)
  146.                         // this is a secure delegate so we need to unwrap and check the inner one
  147.                         return (d._invocationList as Delegate).Equals(this);
  148.                     return false;
  149.                 }
  150.                
  151.                 // now we can call on the base
  152.                 return base.Equals(d);
  153.             }
  154.         }
  155.        
  156.         // Recursive function which will check for equality of the invocation list.
  157.         private bool InvocationListEquals(MulticastDelegate d)
  158.         {
  159.             BCLDebug.Assert(d != null && (_invocationList as object[]) != null, "bogus delegate in multicast list comparison");
  160.             object[] invocationList = _invocationList as object[];
  161.             if (d._invocationCount != _invocationCount)
  162.                 return false;
  163.            
  164.             int invocationCount = (int)_invocationCount;
  165.             for (int i = 0; i < invocationCount; i++) {
  166.                 Delegate dd = (Delegate)invocationList[i];
  167.                 object[] dInvocationList = d._invocationList as object[];
  168.                 if (!dd.Equals(dInvocationList[i]))
  169.                     return false;
  170.             }
  171.             return true;
  172.         }
  173.        
  174.         private bool TrySetSlot(object[] a, int index, object o)
  175.         {
  176.             if (a[index] == null && System.Threading.Interlocked.CompareExchange(ref a[index], o, null) == null)
  177.                 return true;
  178.            
  179.             // The slot may be already set because we have added and removed the same method before.
  180.             // Optimize this case, because it's cheaper than copying the array.
  181.             if (a[index] != null) {
  182.                 MulticastDelegate d = (MulticastDelegate)o;
  183.                 MulticastDelegate dd = (MulticastDelegate)a[index];
  184.                
  185.                 if (dd._methodPtr == d._methodPtr && dd._target == d._target && dd._methodPtrAux == d._methodPtrAux) {
  186.                     return true;
  187.                 }
  188.             }
  189.             return false;
  190.         }
  191.        
  192.         internal MulticastDelegate NewMulticastDelegate(object[] invocationList, int invocationCount, bool thisIsMultiCastAlready)
  193.         {
  194.             // First, allocate a new multicast delegate just like this one, i.e. same type as the this object
  195.             MulticastDelegate result = (MulticastDelegate)InternalAllocLike(this);
  196.            
  197.             // Performance optimization - if this already points to a true multicast delegate,
  198.             // copy _methodPtr and _methodPtrAux fields rather than calling into the EE to get them
  199.             if (thisIsMultiCastAlready) {
  200.                 result._methodPtr = this._methodPtr;
  201.                 result._methodPtrAux = this._methodPtrAux;
  202.             }
  203.             else {
  204.                 result._methodPtr = GetMulticastInvoke();
  205.                 result._methodPtrAux = GetInvokeMethod();
  206.             }
  207.             result._target = result;
  208.             result._invocationList = invocationList;
  209.             result._invocationCount = (IntPtr)invocationCount;
  210.            
  211.             return result;
  212.         }
  213.        
  214.         internal MulticastDelegate NewMulticastDelegate(object[] invocationList, int invocationCount)
  215.         {
  216.             return NewMulticastDelegate(invocationList, invocationCount, false);
  217.         }
  218.        
  219.         internal void StoreDynamicMethod(MethodInfo dynamicMethod)
  220.         {
  221.             if (_invocationCount != (IntPtr)0) {
  222.                 BCLDebug.Assert(!IsUnmanagedFunctionPtr(), "dynamic method and unmanaged fntptr delegate combined");
  223.                 // must be a secure one, unwrap and save
  224.                 MulticastDelegate d = (MulticastDelegate)_invocationList;
  225.                 d._methodBase = dynamicMethod;
  226.                
  227.             }
  228.             else
  229.                 _methodBase = dynamicMethod;
  230.         }
  231.        
  232.         // This method will combine this delegate with the passed delegate
  233.         // to form a new delegate.
  234.         protected override sealed Delegate CombineImpl(Delegate follow)
  235.         {
  236.             // Verify that the types are the same...
  237.             // Actually, we don't need to do this, because Delegate.Combine already checks this.
  238.             // if (!InternalEqualTypes(this, follow)
  239.             // throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));
  240.            
  241.             MulticastDelegate dFollow = (MulticastDelegate)follow;
  242.             object[] resultList;
  243.             int followCount = 1;
  244.             object[] followList = dFollow._invocationList as object[];
  245.             if (followList != null)
  246.                 followCount = (int)dFollow._invocationCount;
  247.            
  248.             int resultCount;
  249.             object[] invocationList = _invocationList as object[];
  250.             if (invocationList == null) {
  251.                 resultCount = 1 + followCount;
  252.                 resultList = new object[resultCount];
  253.                 resultList[0] = this;
  254.                 if (followList == null) {
  255.                     resultList[1] = dFollow;
  256.                 }
  257.                 else {
  258.                     for (int i = 0; i < followCount; i++)
  259.                         resultList[1 + i] = followList[i];
  260.                 }
  261.                 return NewMulticastDelegate(resultList, resultCount);
  262.             }
  263.             else {
  264.                 int invocationCount = (int)_invocationCount;
  265.                 resultCount = invocationCount + followCount;
  266.                 resultList = null;
  267.                 if (resultCount <= invocationList.Length) {
  268.                     resultList = invocationList;
  269.                     if (followList == null) {
  270.                         if (!TrySetSlot(resultList, invocationCount, dFollow))
  271.                             resultList = null;
  272.                     }
  273.                     else {
  274.                         for (int i = 0; i < followCount; i++) {
  275.                             if (!TrySetSlot(resultList, invocationCount + i, followList[i])) {
  276.                                 resultList = null;
  277.                                 break;
  278.                             }
  279.                         }
  280.                     }
  281.                 }
  282.                
  283.                 if (resultList == null) {
  284.                     int allocCount = invocationList.Length;
  285.                     while (allocCount < resultCount)
  286.                         allocCount *= 2;
  287.                    
  288.                     resultList = new object[allocCount];
  289.                    
  290.                     for (int i = 0; i < invocationCount; i++)
  291.                         resultList[i] = invocationList[i];
  292.                    
  293.                     if (followList == null) {
  294.                         resultList[invocationCount] = dFollow;
  295.                     }
  296.                     else {
  297.                         for (int i = 0; i < followCount; i++)
  298.                             resultList[invocationCount + i] = followList[i];
  299.                     }
  300.                 }
  301.                 return NewMulticastDelegate(resultList, resultCount, true);
  302.             }
  303.         }
  304.        
  305.         private object[] DeleteFromInvocationList(object[] invocationList, int invocationCount, int deleteIndex, int deleteCount)
  306.         {
  307.             object[] thisInvocationList = _invocationList as object[];
  308.             int allocCount = thisInvocationList.Length;
  309.             while (allocCount / 2 >= invocationCount - deleteCount)
  310.                 allocCount /= 2;
  311.            
  312.             object[] newInvocationList = new object[allocCount];
  313.            
  314.             for (int i = 0; i < deleteIndex; i++)
  315.                 newInvocationList[i] = invocationList[i];
  316.            
  317.             for (int i = deleteIndex + deleteCount; i < invocationCount; i++)
  318.                 newInvocationList[i - deleteCount] = invocationList[i];
  319.            
  320.             return newInvocationList;
  321.         }
  322.        
  323.         private bool EqualInvocationLists(object[] a, object[] b, int start, int count)
  324.         {
  325.             for (int i = 0; i < count; i++) {
  326.                 if (!(a[start + i].Equals(b[i])))
  327.                     return false;
  328.             }
  329.             return true;
  330.         }
  331.        
  332.         // This method currently looks backward on the invocation list
  333.         // for an element that has Delegate based equality with value. (Doesn't
  334.         // look at the invocation list.) If this is found we remove it from
  335.         // this list and return a new delegate. If its not found a copy of the
  336.         // current list is returned.
  337.         protected override sealed Delegate RemoveImpl(Delegate value)
  338.         {
  339.             // There is a special case were we are removing using a delegate as
  340.             // the value we need to check for this case
  341.             //
  342.             MulticastDelegate v = value as MulticastDelegate;
  343.            
  344.             if (v == null)
  345.                 return this;
  346.             if (v._invocationList as object[] == null) {
  347.                 object[] invocationList = _invocationList as object[];
  348.                 if (invocationList == null) {
  349.                     // they are both not real Multicast
  350.                     if (this.Equals(value))
  351.                         return null;
  352.                 }
  353.                 else {
  354.                     int invocationCount = (int)_invocationCount;
  355.                     for (int i = invocationCount; --i >= 0;) {
  356.                         if (value.Equals(invocationList[i])) {
  357.                             if (invocationCount == 2) {
  358.                                 // Special case - only one value left, either at the beginning or the end
  359.                                 return (Delegate)invocationList[1 - i];
  360.                             }
  361.                             else {
  362.                                 object[] list = DeleteFromInvocationList(invocationList, invocationCount, i, 1);
  363.                                 return NewMulticastDelegate(list, invocationCount - 1, true);
  364.                             }
  365.                         }
  366.                     }
  367.                 }
  368.             }
  369.             else {
  370.                 object[] invocationList = _invocationList as object[];
  371.                 if (invocationList != null) {
  372.                     int invocationCount = (int)_invocationCount;
  373.                     int vInvocationCount = (int)v._invocationCount;
  374.                     for (int i = invocationCount - vInvocationCount; i >= 0; i--) {
  375.                         if (EqualInvocationLists(invocationList, v._invocationList as object[], i, vInvocationCount)) {
  376.                             if (invocationCount - vInvocationCount == 0) {
  377.                                 // Special case - no values left
  378.                                 return null;
  379.                             }
  380.                             else if (invocationCount - vInvocationCount == 1) {
  381.                                 // Special case - only one value left, either at the beginning or the end
  382.                                 return (Delegate)invocationList[i != 0 ? 0 : invocationCount - 1];
  383.                             }
  384.                             else {
  385.                                 object[] list = DeleteFromInvocationList(invocationList, invocationCount, i, vInvocationCount);
  386.                                 return NewMulticastDelegate(list, invocationCount - vInvocationCount, true);
  387.                             }
  388.                         }
  389.                     }
  390.                 }
  391.             }
  392.            
  393.             return this;
  394.         }
  395.        
  396.         // This method returns the Invocation list of this multicast delegate.
  397.         public override sealed Delegate[] GetInvocationList()
  398.         {
  399.             Delegate[] del;
  400.             object[] invocationList = _invocationList as object[];
  401.             if (invocationList == null) {
  402.                 del = new Delegate[1];
  403.                 del[0] = this;
  404.             }
  405.             else {
  406.                 // Create an array of delegate copies and each
  407.                 // element into the array
  408.                 int invocationCount = (int)_invocationCount;
  409.                 del = new Delegate[invocationCount];
  410.                
  411.                 for (int i = 0; i < invocationCount; i++)
  412.                     del[i] = (Delegate)invocationList[i];
  413.             }
  414.             return del;
  415.         }
  416.        
  417.         public static bool operator ==(MulticastDelegate d1, MulticastDelegate d2)
  418.         {
  419.             if ((object)d1 == null)
  420.                 return (object)d2 == null;
  421.            
  422.             return d1.Equals(d2);
  423.         }
  424.        
  425.         public static bool operator !=(MulticastDelegate d1, MulticastDelegate d2)
  426.         {
  427.             if ((object)d1 == null)
  428.                 return (object)d2 != null;
  429.            
  430.             return !d1.Equals(d2);
  431.         }
  432.        
  433.         public override sealed int GetHashCode()
  434.         {
  435.             if (IsUnmanagedFunctionPtr())
  436.                 return unchecked((int)((long)this._methodPtr));
  437.            
  438.             object[] invocationList = _invocationList as object[];
  439.             if (invocationList == null) {
  440.                 return base.GetHashCode();
  441.             }
  442.             else {
  443.                 int hash = 0;
  444.                 for (int i = 0; i < (int)_invocationCount; i++) {
  445.                     hash = hash * 33 + invocationList[i].GetHashCode();
  446.                 }
  447.                
  448.                 return hash;
  449.             }
  450.         }
  451.        
  452.         internal override object GetTarget()
  453.         {
  454.             if (_invocationCount != (IntPtr)0) {
  455.                 // _invocationCount != 0 we are in one of these cases:
  456.                 // - Multicast -> return the target of the last delegate in the list
  457.                 // - Secure delegate -> return the target of the inner delegate
  458.                 // - unmanaged function pointer - return null
  459.                 // - virtual open delegate - return base.GetTarget()
  460.                 if (_invocationList == null) {
  461.                     // both open virtual and ftn pointer return null for the target
  462.                     return null;
  463.                 }
  464.                 else {
  465.                     object[] invocationList = _invocationList as object[];
  466.                     if (invocationList != null) {
  467.                         int invocationCount = (int)_invocationCount;
  468.                         return ((Delegate)invocationList[invocationCount - 1]).GetTarget();
  469.                     }
  470.                     else {
  471.                         Delegate receiver = _invocationList as Delegate;
  472.                         if (receiver != null)
  473.                             return receiver.GetTarget();
  474.                     }
  475.                 }
  476.             }
  477.             return base.GetTarget();
  478.         }
  479.        
  480.         protected override MethodInfo GetMethodImpl()
  481.         {
  482.             if (_invocationCount != (IntPtr)0 && _invocationList != null) {
  483.                 // multicast case
  484.                 object[] invocationList = _invocationList as object[];
  485.                 if (invocationList != null) {
  486.                     int index = (int)_invocationCount - 1;
  487.                     return ((Delegate)invocationList[index]).Method;
  488.                 }
  489.                 else {
  490.                     // must be a secure delegate
  491.                     return ((MulticastDelegate)_invocationList).GetMethodImpl();
  492.                 }
  493.             }
  494.             return base.GetMethodImpl();
  495.         }
  496.        
  497.         // this should help inlining
  498.         [System.Diagnostics.DebuggerNonUserCode()]
  499.         private void ThrowNullThisInDelegateToInstance()
  500.         {
  501.             throw new ArgumentException(Environment.GetResourceString("Arg_DlgtNullInst"));
  502.         }
  503.        
  504.         [System.Diagnostics.DebuggerNonUserCode()]
  505.         private void CtorClosed(object target, IntPtr methodPtr)
  506.         {
  507.             if (target == null)
  508.                 ThrowNullThisInDelegateToInstance();
  509.             this._target = target;
  510.             this._methodPtr = methodPtr;
  511.         }
  512.        
  513.         [System.Diagnostics.DebuggerNonUserCode()]
  514.         private void CtorClosedStatic(object target, IntPtr methodPtr)
  515.         {
  516.             this._target = target;
  517.             this._methodPtr = methodPtr;
  518.         }
  519.        
  520.         [System.Diagnostics.DebuggerNonUserCode()]
  521.         private void CtorRTClosed(object target, IntPtr methodPtr)
  522.         {
  523.             this._target = target;
  524.             this._methodPtr = AdjustTarget(target, methodPtr);
  525.         }
  526.        
  527.         [System.Diagnostics.DebuggerNonUserCode()]
  528.         private void CtorOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk)
  529.         {
  530.             this._target = this;
  531.             this._methodPtr = shuffleThunk;
  532.             this._methodPtrAux = methodPtr;
  533.         }
  534.        
  535.         [System.Diagnostics.DebuggerNonUserCode()]
  536.         private void CtorSecureClosed(object target, IntPtr methodPtr, IntPtr callThunk, IntPtr assembly)
  537.         {
  538.             MulticastDelegate realDelegate = (MulticastDelegate)Delegate.InternalAlloc(Type.GetTypeHandle(this));
  539.             realDelegate.CtorClosed(target, methodPtr);
  540.             this._invocationList = realDelegate;
  541.             this._target = this;
  542.             this._methodPtr = callThunk;
  543.             this._methodPtrAux = assembly;
  544.             this._invocationCount = GetInvokeMethod();
  545.         }
  546.        
  547.         [System.Diagnostics.DebuggerNonUserCode()]
  548.         private void CtorSecureClosedStatic(object target, IntPtr methodPtr, IntPtr callThunk, IntPtr assembly)
  549.         {
  550.             MulticastDelegate realDelegate = (MulticastDelegate)Delegate.InternalAlloc(Type.GetTypeHandle(this));
  551.             realDelegate.CtorClosedStatic(target, methodPtr);
  552.             this._invocationList = realDelegate;
  553.             this._target = this;
  554.             this._methodPtr = callThunk;
  555.             this._methodPtrAux = assembly;
  556.             this._invocationCount = GetInvokeMethod();
  557.         }
  558.        
  559.         [System.Diagnostics.DebuggerNonUserCode()]
  560.         private void CtorSecureRTClosed(object target, IntPtr methodPtr, IntPtr callThunk, IntPtr assembly)
  561.         {
  562.             MulticastDelegate realDelegate = Delegate.InternalAlloc(Type.GetTypeHandle(this));
  563.             realDelegate.CtorRTClosed(target, methodPtr);
  564.             this._invocationList = realDelegate;
  565.             this._target = this;
  566.             this._methodPtr = callThunk;
  567.             this._methodPtrAux = assembly;
  568.             this._invocationCount = GetInvokeMethod();
  569.         }
  570.        
  571.         [System.Diagnostics.DebuggerNonUserCode()]
  572.         private void CtorSecureOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr assembly)
  573.         {
  574.             MulticastDelegate realDelegate = Delegate.InternalAlloc(Type.GetTypeHandle(this));
  575.             realDelegate.CtorOpened(target, methodPtr, shuffleThunk);
  576.             this._invocationList = realDelegate;
  577.             this._target = this;
  578.             this._methodPtr = callThunk;
  579.             this._methodPtrAux = assembly;
  580.             this._invocationCount = GetInvokeMethod();
  581.         }
  582.        
  583.         [System.Diagnostics.DebuggerNonUserCode()]
  584.         private void CtorVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk)
  585.         {
  586.             this._target = this;
  587.             this._methodPtr = shuffleThunk;
  588.             this._methodPtrAux = GetCallStub(methodPtr);
  589.         }
  590.        
  591.         [System.Diagnostics.DebuggerNonUserCode()]
  592.         private void CtorSecureVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr assembly)
  593.         {
  594.             MulticastDelegate realDelegate = Delegate.InternalAlloc(Type.GetTypeHandle(this));
  595.             realDelegate.CtorVirtualDispatch(target, methodPtr, shuffleThunk);
  596.             this._invocationList = realDelegate;
  597.             this._target = this;
  598.             this._methodPtr = callThunk;
  599.             this._methodPtrAux = assembly;
  600.             this._invocationCount = GetInvokeMethod();
  601.         }
  602.     }
  603. }

Developer Fusion