The Labs \ Source Viewer \ SSCLI \ System \ DelegateBindingFlags

  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.    
  18.     using System;
  19.     using System.Reflection;
  20.     using System.Threading;
  21.     using System.Runtime.Serialization;
  22.     using System.Runtime.InteropServices;
  23.     using System.Runtime.CompilerServices;
  24.     [Serializable()]
  25.     [ClassInterface(ClassInterfaceType.AutoDual)]
  26.     [System.Runtime.InteropServices.ComVisible(true)]
  27.     public abstract class Delegate : ICloneable, ISerializable
  28.     {
  29.         // _target is the object we will invoke on
  30.         internal object _target;
  31.        
  32.         // MethodBase, either cached after first request or assigned from a DynamicMethod
  33.         internal MethodBase _methodBase;
  34.        
  35.         // _methodPtr is a pointer to the method we will invoke
  36.         // It could be a small thunk if this is a static or UM call
  37.         internal IntPtr _methodPtr;
  38.        
  39.         // In the case of a static method passed to a delegate, this field stores
  40.         // whatever _methodPtr would have stored: and _methodPtr points to a
  41.         // small thunk which removes the "this" pointer before going on
  42.         // to _methodPtrAux.
  43.         internal IntPtr _methodPtrAux;
  44.        
  45.         // This constructor is called from the class generated by the
  46.         // compiler generated code
  47.         protected Delegate(object target, string method)
  48.         {
  49.             if (target == null)
  50.                 throw new ArgumentNullException("target");
  51.            
  52.             if (method == null)
  53.                 throw new ArgumentNullException("method");
  54.            
  55.             // This API existed in v1/v1.1 and only expected to create closed
  56.             // instance delegates. Constrain the call to BindToMethodName to
  57.             // such and don't allow relaxed signature matching (which could make
  58.             // the choice of target method ambiguous) for backwards
  59.             // compatibility. The name matching was case sensitive and we
  60.             // preserve that as well.
  61.             if (!BindToMethodName(target, Type.GetTypeHandle(target), method, DelegateBindingFlags.InstanceMethodOnly | DelegateBindingFlags.ClosedDelegateOnly))
  62.                 throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
  63.         }
  64.        
  65.         // This constructor is called from a class to generate a
  66.         // delegate based upon a static method name and the Type object
  67.         // for the class defining the method.
  68.         unsafe protected Delegate(Type target, string method)
  69.         {
  70.             if (target == null)
  71.                 throw new ArgumentNullException("target");
  72.            
  73.             if (!(target is RuntimeType))
  74.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "target");
  75.            
  76.             if (target.IsGenericType && target.ContainsGenericParameters)
  77.                 throw new ArgumentException(Environment.GetResourceString("Arg_UnboundGenParam"), "target");
  78.            
  79.             if (method == null)
  80.                 throw new ArgumentNullException("method");
  81.            
  82.             // This API existed in v1/v1.1 and only expected to create open
  83.             // static delegates. Constrain the call to BindToMethodName to such
  84.             // and don't allow relaxed signature matching (which could make the
  85.             // choice of target method ambiguous) for backwards compatibility.
  86.             // The name matching was case insensitive (no idea why this is
  87.             // different from the constructor above) and we preserve that as
  88.             // well.
  89.             BindToMethodName(null, target.TypeHandle, method, DelegateBindingFlags.StaticMethodOnly | DelegateBindingFlags.OpenDelegateOnly | DelegateBindingFlags.CaselessMatching);
  90.         }
  91.        
  92.         // Protect the default constructor so you can't build a delegate
  93.         private Delegate()
  94.         {
  95.         }
  96.        
  97.         public object DynamicInvoke(params object[] args)
  98.         {
  99.             return DynamicInvokeImpl(args);
  100.         }
  101.        
  102.         protected virtual object DynamicInvokeImpl(object[] args)
  103.         {
  104.             RuntimeMethodHandle method = new RuntimeMethodHandle(GetInvokeMethod());
  105.             RuntimeTypeHandle delegateType = Type.GetTypeHandle(this);
  106.             RuntimeMethodInfo invoke = (RuntimeMethodInfo)RuntimeType.GetMethodBase(delegateType, method);
  107.             return invoke.Invoke(this, BindingFlags.Default, null, args, null, true);
  108.         }
  109.        
  110.        
  111.         public override bool Equals(object obj)
  112.         {
  113.             if (obj == null || !InternalEqualTypes(this, obj))
  114.                 return false;
  115.            
  116.             Delegate d = (Delegate)obj;
  117.            
  118.             // do an optimistic check first. This is hopefully cheap enough to be worth
  119.             if (_target == d._target && _methodPtr == d._methodPtr && _methodPtrAux == d._methodPtrAux)
  120.                 return true;
  121.            
  122.             // even though the fields were not all equals the delegates may still match
  123.             // When target carries the delegate itself the 2 targets (delegates) may be different instances
  124.             // but the delegates are logically the same
  125.             // It may also happen that the method pointer was not jitted when creating one delegate and jitted in the other
  126.             // if that's the case the delegates may still be equals but we need to make a more complicated check
  127.            
  128.             if (_methodPtrAux.IsNull()) {
  129.                 if (!d._methodPtrAux.IsNull())
  130.                     return false;
  131.                 // different delegate kind
  132.                 // they are both closed over the first arg
  133.                 if (_target != d._target)
  134.                     return false;
  135.                 // fall through method handle check
  136.             }
  137.             else {
  138.                 if (d._methodPtrAux.IsNull())
  139.                     return false;
  140.                 // different delegate kind
  141.                 // Ignore the target as it will be the delegate instance, though it may be a different one
  142.                 /*
  143.                 if (_methodPtr != d._methodPtr)
  144.                     return false;
  145.                     */               
  146.                
  147. if (_methodPtrAux == d._methodPtrAux)
  148.                     return true;
  149.                 // fall through method handle check
  150.             }
  151.            
  152.             // method ptrs don't match, go down long path
  153.             //
  154.             if (_methodBase == null || d._methodBase == null)
  155.                 return FindMethodHandle().Equals(d.FindMethodHandle());
  156.             else
  157.                 return _methodBase.Equals(d._methodBase);
  158.            
  159.         }
  160.        
  161.         public override int GetHashCode()
  162.         {
  163.             //
  164.             // this is not right in the face of a method being jitted in one delegate and not in another
  165.             // in that case the delegate is the same and Equals will return true but GetHashCode returns a
  166.             // different hashcode which is not true.
  167.             /*
  168.             if (_methodPtrAux.IsNull())
  169.                 return unchecked((int)((long)this._methodPtr));
  170.             else
  171.                 return unchecked((int)((long)this._methodPtrAux));
  172.             */           
  173. return GetType().GetHashCode();
  174.         }
  175.        
  176.         public static Delegate Combine(Delegate a, Delegate b)
  177.         {
  178.             // boundry conditions -- if either (or both) delegates is null
  179.             // return the other.
  180.             if ((object)a == null)
  181.                 // cast to object for a more efficient test
  182.                 return b;
  183.             if ((object)b == null)
  184.                 // cast to object for a more efficient test
  185.                 return a;
  186.            
  187.             if (!InternalEqualTypes(a, b))
  188.                 throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));
  189.            
  190.             return a.CombineImpl(b);
  191.         }
  192.        
  193.         [System.Runtime.InteropServices.ComVisible(true)]
  194.         public static Delegate Combine(params Delegate[] delegates)
  195.         {
  196.             if (delegates == null || delegates.Length == 0)
  197.                 return null;
  198.            
  199.             Delegate d = delegates[0];
  200.             for (int i = 1; i < delegates.Length; i++)
  201.                 d = Combine(d, delegates[i]);
  202.            
  203.             return d;
  204.         }
  205.        
  206.         public virtual Delegate[] GetInvocationList()
  207.         {
  208.             Delegate[] d = new Delegate[1];
  209.             d[0] = this;
  210.             return d;
  211.         }
  212.        
  213.         // This routine will return the method
  214.         public MethodInfo Method {
  215.             get { return GetMethodImpl(); }
  216.         }
  217.        
  218.         protected virtual MethodInfo GetMethodImpl()
  219.         {
  220.             if (_methodBase == null) {
  221.                 RuntimeMethodHandle method = FindMethodHandle();
  222.                 RuntimeTypeHandle declaringType = method.GetDeclaringType();
  223.                 // need a proper declaring type instance method on a generic type
  224.                 if (declaringType.IsGenericTypeDefinition() || declaringType.HasInstantiation()) {
  225.                     bool isStatic = (method.GetAttributes() & MethodAttributes.Static) != (MethodAttributes)0;
  226.                     if (!isStatic) {
  227.                         if (_methodPtrAux == (IntPtr)0) {
  228.                             declaringType = _target.GetType().TypeHandle;
  229.                             // may throw NullRefException if the this is null but that's ok
  230.                         }
  231.                         else {
  232.                             // it's an open one, need to fetch the first arg of the instantiation
  233.                             MethodInfo invoke = this.GetType().GetMethod("Invoke");
  234.                             declaringType = invoke.GetParameters()[0].ParameterType.TypeHandle;
  235.                         }
  236.                     }
  237.                 }
  238.                 _methodBase = (MethodInfo)RuntimeType.GetMethodBase(declaringType, method);
  239.             }
  240.             return (MethodInfo)_methodBase;
  241.         }
  242.        
  243.         public object Target {
  244.             get { return GetTarget(); }
  245.         }
  246.        
  247.        
  248.         public static Delegate Remove(Delegate source, Delegate value)
  249.         {
  250.             if (source == null)
  251.                 return null;
  252.            
  253.             if (value == null)
  254.                 return source;
  255.            
  256.             if (!InternalEqualTypes(source, value))
  257.                 throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));
  258.            
  259.             return source.RemoveImpl(value);
  260.         }
  261.        
  262.         public static Delegate RemoveAll(Delegate source, Delegate value)
  263.         {
  264.             Delegate newDelegate = null;
  265.            
  266.             do {
  267.                 newDelegate = source;
  268.                 source = Remove(source, value);
  269.             }
  270.             while (newDelegate != source);
  271.            
  272.             return newDelegate;
  273.         }
  274.        
  275.         protected virtual Delegate CombineImpl(Delegate d)
  276.         {
  277.             throw new MulticastNotSupportedException(Environment.GetResourceString("Multicast_Combine"));
  278.         }
  279.        
  280.         protected virtual Delegate RemoveImpl(Delegate d)
  281.         {
  282.             return (d.Equals(this)) ? null : this;
  283.         }
  284.        
  285.        
  286.         public virtual object Clone()
  287.         {
  288.             return MemberwiseClone();
  289.         }
  290.        
  291.         // V1 API.
  292.         public static Delegate CreateDelegate(Type type, object target, string method)
  293.         {
  294.             return CreateDelegate(type, target, method, false, true);
  295.         }
  296.        
  297.         // V1 API.
  298.         public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase)
  299.         {
  300.             return CreateDelegate(type, target, method, ignoreCase, true);
  301.         }
  302.        
  303.         // V1 API.
  304.         public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure)
  305.         {
  306.             if (type == null)
  307.                 throw new ArgumentNullException("type");
  308.             if (!(type is RuntimeType))
  309.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
  310.             if (target == null)
  311.                 throw new ArgumentNullException("target");
  312.             if (method == null)
  313.                 throw new ArgumentNullException("method");
  314.             Type c = type.BaseType;
  315.             if (c == null || c != typeof(MulticastDelegate))
  316.                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
  317.            
  318.             Delegate d = InternalAlloc(type.TypeHandle);
  319.             // This API existed in v1/v1.1 and only expected to create closed
  320.             // instance delegates. Constrain the call to BindToMethodName to such
  321.             // and don't allow relaxed signature matching (which could make the
  322.             // choice of target method ambiguous) for backwards compatibility.
  323.             // We never generate a closed over null delegate and this is
  324.             // actually enforced via the check on target above, but we pass
  325.             // NeverCloseOverNull anyway just for clarity.
  326.             if (!d.BindToMethodName(target, Type.GetTypeHandle(target), method, DelegateBindingFlags.InstanceMethodOnly | DelegateBindingFlags.ClosedDelegateOnly | DelegateBindingFlags.NeverCloseOverNull | (ignoreCase ? DelegateBindingFlags.CaselessMatching : 0))) {
  327.                 if (throwOnBindFailure)
  328.                     throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
  329.                 d = null;
  330.             }
  331.            
  332.             return d;
  333.         }
  334.        
  335.         // V1 API.
  336.         public static Delegate CreateDelegate(Type type, Type target, string method)
  337.         {
  338.             return CreateDelegate(type, target, method, false, true);
  339.         }
  340.        
  341.         // V1 API.
  342.         public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase)
  343.         {
  344.             return CreateDelegate(type, target, method, ignoreCase, true);
  345.         }
  346.        
  347.         // V1 API.
  348.         public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase, bool throwOnBindFailure)
  349.         {
  350.             if (type == null)
  351.                 throw new ArgumentNullException("type");
  352.             if (!(type is RuntimeType))
  353.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
  354.             if (target == null)
  355.                 throw new ArgumentNullException("target");
  356.             if (!(target is RuntimeType))
  357.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "target");
  358.             if (target.IsGenericType && target.ContainsGenericParameters)
  359.                 throw new ArgumentException(Environment.GetResourceString("Arg_UnboundGenParam"), "target");
  360.             if (method == null)
  361.                 throw new ArgumentNullException("method");
  362.             Type c = type.BaseType;
  363.             if (c == null || c != typeof(MulticastDelegate))
  364.                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
  365.            
  366.             Delegate d = InternalAlloc(type.TypeHandle);
  367.             // This API existed in v1/v1.1 and only expected to create open
  368.             // static delegates. Constrain the call to BindToMethodName to such
  369.             // and don't allow relaxed signature matching (which could make the
  370.             // choice of target method ambiguous) for backwards compatibility.
  371.             if (!d.BindToMethodName(null, target.TypeHandle, method, DelegateBindingFlags.StaticMethodOnly | DelegateBindingFlags.OpenDelegateOnly | (ignoreCase ? DelegateBindingFlags.CaselessMatching : 0))) {
  372.                 if (throwOnBindFailure)
  373.                     throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
  374.                 d = null;
  375.             }
  376.            
  377.             return d;
  378.         }
  379.        
  380.         // V1 API.
  381.         public static Delegate CreateDelegate(Type type, MethodInfo method)
  382.         {
  383.             return CreateDelegate(type, method, true);
  384.         }
  385.        
  386.         // V1 API.
  387.         public static Delegate CreateDelegate(Type type, MethodInfo method, bool throwOnBindFailure)
  388.         {
  389.             // Validate the parameters.
  390.             if (type == null)
  391.                 throw new ArgumentNullException("type");
  392.             if (!(type is RuntimeType))
  393.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
  394.             if (method == null)
  395.                 throw new ArgumentNullException("method");
  396.             if (!(method is RuntimeMethodInfo))
  397.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "method");
  398.             Type c = type.BaseType;
  399.             if (c == null || c != typeof(MulticastDelegate))
  400.                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
  401.            
  402.             // Initialize the delegate...
  403.             Delegate d = InternalAlloc(type.TypeHandle);
  404.             // This API existed in v1/v1.1 and only expected to create closed
  405.             // instance delegates. Constrain the call to BindToMethodInfo to
  406.             // open delegates only for backwards compatibility. But we'll allow
  407.             // relaxed signature checking and open static delegates because
  408.             // there's no ambiguity there (the caller would have to explicitly
  409.             // pass us a static method or a method with a non-exact signature
  410.             // and the only change in behavior from v1.1 there is that we won't
  411.             // fail the call).
  412.             if (!d.BindToMethodInfo(null, method.MethodHandle, method.DeclaringType.TypeHandle, DelegateBindingFlags.OpenDelegateOnly | DelegateBindingFlags.RelaxedSignature)) {
  413.                 if (throwOnBindFailure)
  414.                     throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
  415.                 d = null;
  416.             }
  417.             return d;
  418.         }
  419.        
  420.         // V2 API.
  421.         public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method)
  422.         {
  423.             return CreateDelegate(type, firstArgument, method, true);
  424.         }
  425.        
  426.         // V2 API.
  427.         public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure)
  428.         {
  429.             // Validate the parameters.
  430.             if (type == null)
  431.                 throw new ArgumentNullException("type");
  432.             if (!(type is RuntimeType))
  433.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
  434.             if (method == null)
  435.                 throw new ArgumentNullException("method");
  436.             if (!(method is RuntimeMethodInfo))
  437.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "method");
  438.             Type c = type.BaseType;
  439.             if (c == null || c != typeof(MulticastDelegate))
  440.                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
  441.            
  442.             // Initialize the method...
  443.             Delegate d = InternalAlloc(type.TypeHandle);
  444.             if (!d.BindToMethodInfo(firstArgument, method.MethodHandle, method.DeclaringType.TypeHandle, DelegateBindingFlags.RelaxedSignature)) {
  445.                 if (throwOnBindFailure)
  446.                     throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
  447.                 d = null;
  448.             }
  449.             return d;
  450.         }
  451.        
  452.         public static bool operator ==(Delegate d1, Delegate d2)
  453.         {
  454.             if ((object)d1 == null)
  455.                 return (object)d2 == null;
  456.            
  457.             return d1.Equals(d2);
  458.         }
  459.        
  460.         public static bool operator !=(Delegate d1, Delegate d2)
  461.         {
  462.             if ((object)d1 == null)
  463.                 return (object)d2 != null;
  464.            
  465.             return !d1.Equals(d2);
  466.         }
  467.        
  468.         //
  469.         // Implementation of ISerializable
  470.         //
  471.        
  472.         public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
  473.         {
  474.             throw new NotSupportedException();
  475.         }
  476.         //
  477.         // internal implementation details (FCALLS and utilities)
  478.         //
  479.        
  480.         // V2 internal API.
  481.         unsafe static internal Delegate CreateDelegate(Type type, object target, RuntimeMethodHandle method)
  482.         {
  483.             // Validate the parameters.
  484.             if (type == null)
  485.                 throw new ArgumentNullException("type");
  486.             if (!(type is RuntimeType))
  487.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
  488.             if (method.IsNullHandle())
  489.                 throw new ArgumentNullException("method");
  490.            
  491.             Type c = type.BaseType;
  492.             if (c == null || c != typeof(MulticastDelegate))
  493.                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
  494.            
  495.             // Initialize the method...
  496.             Delegate d = InternalAlloc(type.TypeHandle);
  497.             // This is a new internal API added in Whidbey. Currently it's only
  498.             // used by the dynamic method code to generate a wrapper delegate.
  499.             // Allow flexible binding options since the target method is
  500.             // unambiguously provided to us.
  501.             if (!d.BindToMethodInfo(target, method, method.GetDeclaringType(), DelegateBindingFlags.RelaxedSignature))
  502.                 throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
  503.             return d;
  504.         }
  505.        
  506.         // Caution: this method is intended for deserialization only, no security checks are performed.
  507.         static internal Delegate InternalCreateDelegate(Type type, object firstArgument, MethodInfo method)
  508.         {
  509.             // Validate the parameters.
  510.             if (type == null)
  511.                 throw new ArgumentNullException("type");
  512.             if (method == null)
  513.                 throw new ArgumentNullException("method");
  514.             Type c = type.BaseType;
  515.             if (c == null || c != typeof(MulticastDelegate))
  516.                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
  517.            
  518.             // Initialize the method...
  519.             Delegate d = InternalAlloc(type.TypeHandle);
  520.             // This API is used by the formatters when deserializing a delegate.
  521.             // They pass us the specific target method (that was already the
  522.             // target in a valid delegate) so we should bind with the most
  523.             // relaxed rules available (the result will never be ambiguous, it
  524.             // just increases the chance of success with minor (compatible)
  525.             // signature changes). We explicitly skip security checks here --
  526.             // we're not really constructing a delegate, we're cloning an
  527.             // existing instance which already passed its checks.
  528.             if (!d.BindToMethodInfo(firstArgument, method.MethodHandle, method.DeclaringType.TypeHandle, DelegateBindingFlags.SkipSecurityChecks | DelegateBindingFlags.RelaxedSignature))
  529.                 throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
  530.            
  531.             return d;
  532.         }
  533.        
  534.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  535.         private extern bool BindToMethodName(object target, RuntimeTypeHandle methodType, string method, DelegateBindingFlags flags);
  536.        
  537.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  538.         private extern bool BindToMethodInfo(object target, RuntimeMethodHandle method, RuntimeTypeHandle methodType, DelegateBindingFlags flags);
  539.        
  540.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  541.         static internal extern MulticastDelegate InternalAlloc(RuntimeTypeHandle type);
  542.        
  543.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  544.         static internal extern MulticastDelegate InternalAllocLike(Delegate d);
  545.        
  546.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  547.         static internal extern bool InternalEqualTypes(object a, object b);
  548.        
  549.         // Used by the ctor. Do not call directly.
  550.         // The name of this function will appear in managed stacktraces as delegate constructor.
  551.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  552.         private extern void DelegateConstruct(object target, IntPtr slot);
  553.        
  554.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  555.         internal extern IntPtr GetMulticastInvoke();
  556.        
  557.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  558.         internal extern IntPtr GetInvokeMethod();
  559.        
  560.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  561.         internal extern RuntimeMethodHandle FindMethodHandle();
  562.        
  563.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  564.         internal extern IntPtr GetUnmanagedCallSite();
  565.        
  566.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  567.         internal extern IntPtr AdjustTarget(object target, IntPtr methodPtr);
  568.        
  569.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  570.         internal extern IntPtr GetCallStub(IntPtr methodPtr);
  571.        
  572.         internal virtual object GetTarget()
  573.         {
  574.             return (_methodPtrAux.IsNull()) ? _target : null;
  575.         }
  576.        
  577.        
  578.     }
  579.    
  580.     // These flags effect the way BindToMethodInfo and BindToMethodName are allowed to bind a delegate to a target method. Their
  581.     // values must be kept in sync with the definition in vm\comdelegate.h.
  582.     internal enum DelegateBindingFlags
  583.     {
  584.         StaticMethodOnly = 1,
  585.         // Can only bind to static target methods
  586.         InstanceMethodOnly = 2,
  587.         // Can only bind to instance (including virtual) methods
  588.         OpenDelegateOnly = 4,
  589.         // Only allow the creation of delegates open over the 1st argument
  590.         ClosedDelegateOnly = 8,
  591.         // Only allow the creation of delegates closed over the 1st argument
  592.         NeverCloseOverNull = 16,
  593.         // A null target will never been considered as a possible null 1st argument
  594.         CaselessMatching = 32,
  595.         // Use case insensitive lookup for methods matched by name
  596.         SkipSecurityChecks = 64,
  597.         // Skip security checks (visibility, link demand etc.)
  598.         RelaxedSignature = 128
  599.         // Allow relaxed signature matching (co/contra variance)
  600.     }
  601. }

Developer Fusion