MethodBase::Invoke Method (Object, BindingFlags, Binder, array<Object>, CultureInfo)

When overridden in a derived class, invokes the reflected method or constructor with the given parameters.

Namespace:  System.Reflection
Assembly:  mscorlib (in mscorlib.dll)

public:
virtual Object^ Invoke(
	Object^ obj, 
	BindingFlags invokeAttr, 
	Binder^ binder, 
	array<Object^>^ parameters, 
	CultureInfo^ culture
) abstract

Parameters

obj
Type: System::Object

The object on which to invoke the method or constructor. If a method is static, this argument is ignored. If a constructor is static, this argument must be nullptr or an instance of the class that defines the constructor.

invokeAttr
Type: System.Reflection::BindingFlags

A bitmask that is a combination of 0 or more bit flags from BindingFlags. If binder is nullptr, this parameter is assigned the value Default; thus, whatever you pass in is ignored.

binder
Type: System.Reflection::Binder

An object that enables the binding, coercion of argument types, invocation of members, and retrieval of MemberInfo objects via reflection. If binder is nullptr, the default binder is used.

parameters
Type: array<System::Object>

An argument list for the invoked method or constructor. This is an array of objects with the same number, order, and type as the parameters of the method or constructor to be invoked. If there are no parameters, this should be nullptr.

If the method or constructor represented by this instance takes a ByRef parameter, there is no special attribute required for that parameter in order to invoke the method or constructor using this function. Any object in this array that is not explicitly initialized with a value will contain the default value for that object type. For reference-type elements, this value is nullptr. For value-type elements, this value is 0, 0.0, or false, depending on the specific element type.

culture
Type: System.Globalization::CultureInfo

An instance of CultureInfo used to govern the coercion of types. If this is nullptr, the CultureInfo for the current thread is used. (This is necessary to convert a String that represents 1000 to a Double value, for example, since 1000 is represented differently by different cultures.)

Return Value

Type: System::Object
An Object containing the return value of the invoked method, or nullptr in the case of a constructor, or nullptr if the method's return type is void. Before calling the method or constructor, Invoke checks to see if the user has access permission and verifies that the parameters are valid.
Caution noteCaution

Elements of the parameters array that represent parameters declared with the ref or out keyword may also be modified.

Implements

_MethodBase::Invoke(Object, BindingFlags, Binder, array<Object>, CultureInfo)

ExceptionCondition
TargetException

The obj parameter is nullptr and the method is not static.

-or-

The method is not declared or inherited by the class of obj.

-or-

A static constructor is invoked, and obj is neither nullptr nor an instance of the class that declared the constructor.

ArgumentException

The type of the parameters parameter does not match the signature of the method or constructor reflected by this instance.

TargetParameterCountException

The parameters array does not have the correct number of arguments.

TargetInvocationException

The invoked method or constructor throws an exception.

MethodAccessException

The caller does not have permission to execute the method or constructor that is represented by the current instance.

InvalidOperationException

The type that declares the method is an open generic type. That is, the Type::ContainsGenericParameters property returns true for the declaring type.

Dynamically invokes the method reflected by this instance on obj, and passes along the specified parameters. If the method is static, the obj parameter is ignored. For non-static methods, obj should be an instance of a class that inherits or declares the method and must be the same type as this class. If the method has no parameters, the value of parameters should be nullptr. Otherwise, the number, type, and order of elements in parameters should be identical to the number, type, and order of parameters for the method reflected by this instance.

You may not omit optional parameters in calls to Invoke. To invoke a method omitting optional parameters, you should call Type.InvokeMember instead.

NoteNote

If this method overload is used to invoke an instance constructor, the object supplied for obj is reinitialized; that is, all instance initializers are executed. The return value is nullptr. If a class constructor is invoked, the class is reinitialized; that is, all class initializers are executed. The return value is nullptr.

For pass-by-value primitive parameters, normal widening is performed (Int16 -> Int32, for example). For pass-by-value reference parameters, normal reference widening is allowed (derived class to base class, and base class to interface type). However, for pass-by-reference primitive parameters, the types must match exactly. For pass-by-reference reference parameters, the normal widening still applies.

For example, if the method reflected by this instance is declared as public boolean Compare(String a, String b), then parameters should be an array of Objects with length 2 such that parameters[0] = new Object("SomeString1") and parameters[1] = new Object("SomeString2").

If a parameter of the current method is a value type, and the corresponding argument in parameters is nullptr, the runtime passes a zero-initialized instance of the value type.

Reflection uses dynamic method lookup when invoking virtual methods. For example, suppose that class B inherits from class A and both implement a virtual method named M. Now suppose that you have a MethodInfo object that represents M on class A. If you use the Invoke method to invoke M on an object of type B, then reflection will use the implementation given by class B. Even if the object of type B is cast to A, the implementation given by class B is used (see code sample below).

On the other hand, if the method is non-virtual, then reflection will use the implementation given by the type from which the MethodInfo was obtained, regardless of the type of the object passed as the target.

Access restrictions are ignored for fully trusted code. That is, private constructors, methods, fields, and properties can be accessed and invoked via reflection whenever the code is fully trusted.

If the invoked method throws an exception, TargetInvocationException.GetException returns the exception. This implementation throws a NotSupportedException.

NoteNote

Starting with the .NET Framework 2.0 Service Pack 1, this method can be used to access non-public members if the caller has been granted ReflectionPermission with the ReflectionPermissionFlag::RestrictedMemberAccess flag and if the grant set of the non-public members is restricted to the caller’s grant set, or a subset thereof. (See Security Considerations for Reflection.)

To use this functionality, your application should target the .NET Framework 3.5 or later.

The following example demonstrates all members of the System.Reflection::Binder class using an overload of Type::InvokeMember. The private method CanConvertFrom finds compatible types for a given type. For another example of invoking members in a custom binding scenario, see Dynamically Loading and Using Types.

using namespace System;
using namespace System::Reflection;
using namespace System::Globalization;
using namespace System::Runtime::InteropServices;
public ref class MyBinder: public Binder
{
public:
   MyBinder()
      : Binder()
   {}

private:
   ref class BinderState
   {
   public:
      array<Object^>^args;
   };

public:
   virtual FieldInfo^ BindToField( BindingFlags bindingAttr, array<FieldInfo^>^match, Object^ value, CultureInfo^ culture ) override
   {
      if ( match == nullptr )
            throw gcnew ArgumentNullException( "match" );

      // Get a field for which the value parameter can be converted to the specified field type. 
      for ( int i = 0; i < match->Length; i++ )
         if ( ChangeType( value, match[ i ]->FieldType, culture ) != nullptr )
                  return match[ i ];

      return nullptr;
   }

   virtual MethodBase^ BindToMethod( BindingFlags bindingAttr, array<MethodBase^>^match, array<Object^>^%args, array<ParameterModifier>^ modifiers, CultureInfo^ culture, array<String^>^names, [Out]Object^% state ) override
   {
      // Store the arguments to the method in a state Object*.
      BinderState^ myBinderState = gcnew BinderState;
      array<Object^>^arguments = gcnew array<Object^>(args->Length);
      args->CopyTo( arguments, 0 );
      myBinderState->args = arguments;
      state = myBinderState;
      if ( match == nullptr )
            throw gcnew ArgumentNullException;

      // Find a method that has the same parameters as those of the args parameter. 
      for ( int i = 0; i < match->Length; i++ )
      {
         // Count the number of parameters that match. 
         int count = 0;
         array<ParameterInfo^>^parameters = match[ i ]->GetParameters();

         // Go on to the next method if the number of parameters do not match. 
         if ( args->Length != parameters->Length )
                  continue;

         // Match each of the parameters that the user expects the method to have. 
         for ( int j = 0; j < args->Length; j++ )
         {
            // If the names parameter is not 0, then reorder args. 
            if ( names != nullptr )
            {
               if ( names->Length != args->Length )
                              throw gcnew ArgumentException( "names and args must have the same number of elements." );

               for ( int k = 0; k < names->Length; k++ )
                  if ( String::Compare( parameters[ j ]->Name, names[ k ] ) == 0 )
                                    args[ j ] = myBinderState->args[ k ];
            }

            // Determine whether the types specified by the user can be converted to the parameter type. 
            if ( ChangeType( args[ j ], parameters[ j ]->ParameterType, culture ) != nullptr )
                        count += 1;
            else 
                        break;
         }
         if ( count == args->Length )
                  return match[ i ];
      }
      return nullptr;
   }

   virtual Object^ ChangeType( Object^ value, Type^ myChangeType, CultureInfo^ culture ) override
   {
      // Determine whether the value parameter can be converted to a value of type myType. 
      if ( CanConvertFrom( value->GetType(), myChangeType ) )
         // Return the converted Object*. 
         return Convert::ChangeType( value, myChangeType ); 
      else 
         return nullptr;
   }

   virtual void ReorderArgumentArray( array<Object^>^%args, Object^ state ) override
   {
      // Return the args that had been reordered by BindToMethod.
      (safe_cast<BinderState^>(state))->args->CopyTo( args, 0 );
   }

   virtual MethodBase^ SelectMethod( BindingFlags bindingAttr, array<MethodBase^>^match, array<Type^>^types, array<ParameterModifier>^ modifiers ) override
   {
      if ( match == nullptr )
            throw gcnew ArgumentNullException( "match" );

      for ( int i = 0; i < match->Length; i++ )
      {
         // Count the number of parameters that match. 
         int count = 0;
         array<ParameterInfo^>^parameters = match[ i ]->GetParameters();

         // Go on to the next method if the number of parameters do not match. 
         if ( types->Length != parameters->Length )
                  continue;

         // Match each of the parameters that the user expects the method to have. 
         for ( int j = 0; j < types->Length; j++ )
         {
            // Determine whether the types specified by the user can be converted to parameter type. 
            if ( CanConvertFrom( types[ j ], parameters[ j ]->ParameterType ) )
                        count += 1;
            else 
                        break;
         }
         // Determine whether the method has been found. 
         if ( count == types->Length )
                  return match[ i ];
      }
      return nullptr;
   }

   virtual PropertyInfo^ SelectProperty( BindingFlags bindingAttr, array<PropertyInfo^>^match, Type^ returnType, array<Type^>^indexes, array<ParameterModifier>^ modifiers ) override
   {
      if ( match == nullptr )
            throw gcnew ArgumentNullException( "match" );

      for ( int i = 0; i < match->Length; i++ )
      {
         // Count the number of indexes that match. 
         int count = 0;
         array<ParameterInfo^>^parameters = match[ i ]->GetIndexParameters();

         // Go on to the next property if the number of indexes do not match. 
         if ( indexes->Length != parameters->Length )
                  continue;

         // Match each of the indexes that the user expects the property to have. 
         for ( int j = 0; j < indexes->Length; j++ )
            // Determine whether the types specified by the user can be converted to index type. 
            if ( CanConvertFrom( indexes[ j ], parameters[ j ]->ParameterType ) )
                        count += 1;
            else 
                        break;

         // Determine whether the property has been found. 
         if ( count == indexes->Length )
         {
            // Determine whether the return type can be converted to the properties type. 
            if ( CanConvertFrom( returnType, match[ i ]->PropertyType ) )
                  return match[ i ];
            else 
                  continue;
         }
      }
      return nullptr;
   }

private:

   // Determines whether type1 can be converted to type2. Check only for primitive types. 
   bool CanConvertFrom( Type^ type1, Type^ type2 )
   {
      if ( type1->IsPrimitive && type2->IsPrimitive )
      {
         TypeCode typeCode1 = Type::GetTypeCode( type1 );
         TypeCode typeCode2 = Type::GetTypeCode( type2 );

         // If both type1 and type2 have the same type, return true. 
         if ( typeCode1 == typeCode2 )
                  return true;

         // Possible conversions from Char follow. 
         if ( typeCode1 == TypeCode::Char )
         {
            switch ( typeCode2 )
            {
               case TypeCode::UInt16:
                  return true;

               case TypeCode::UInt32:
                  return true;

               case TypeCode::Int32:
                  return true;

               case TypeCode::UInt64:
                  return true;

               case TypeCode::Int64:
                  return true;

               case TypeCode::Single:
                  return true;

               case TypeCode::Double:
                  return true;

               default:
                  return false;
            }
         }

         // Possible conversions from Byte follow. 
         if ( typeCode1 == TypeCode::Byte )
         {
            switch ( typeCode2 )
            {
               case TypeCode::Char:
                  return true;

               case TypeCode::UInt16:
                  return true;

               case TypeCode::Int16:
                  return true;

               case TypeCode::UInt32:
                  return true;

               case TypeCode::Int32:
                  return true;

               case TypeCode::UInt64:
                  return true;

               case TypeCode::Int64:
                  return true;

               case TypeCode::Single:
                  return true;

               case TypeCode::Double:
                  return true;

               default:
                  return false;
            }
         }

         // Possible conversions from SByte follow. 
         if ( typeCode1 == TypeCode::SByte )
         {
            switch ( typeCode2 )
            {
               case TypeCode::Int16:
                  return true;

               case TypeCode::Int32:
                  return true;

               case TypeCode::Int64:
                  return true;

               case TypeCode::Single:
                  return true;

               case TypeCode::Double:
                  return true;

               default:
                  return false;
            }
         }

         // Possible conversions from UInt16 follow. 
         if ( typeCode1 == TypeCode::UInt16 )
         {
            switch ( typeCode2 )
            {
               case TypeCode::UInt32:
                  return true;

               case TypeCode::Int32:
                  return true;

               case TypeCode::UInt64:
                  return true;

               case TypeCode::Int64:
                  return true;

               case TypeCode::Single:
                  return true;

               case TypeCode::Double:
                  return true;

               default:
                  return false;
            }
         }

         // Possible conversions from Int16 follow. 
         if ( typeCode1 == TypeCode::Int16 )
         {
            switch ( typeCode2 )
            {
               case TypeCode::Int32:
                  return true;

               case TypeCode::Int64:
                  return true;

               case TypeCode::Single:
                  return true;

               case TypeCode::Double:
                  return true;

               default:
                  return false;
            }
         }

         // Possible conversions from UInt32 follow. 
         if ( typeCode1 == TypeCode::UInt32 )
         {
            switch ( typeCode2 )
            {
               case TypeCode::UInt64:
                  return true;

               case TypeCode::Int64:
                  return true;

               case TypeCode::Single:
                  return true;

               case TypeCode::Double:
                  return true;

               default:
                  return false;
            }
         }

         // Possible conversions from Int32 follow. 
         if ( typeCode1 == TypeCode::Int32 )
         {
            switch ( typeCode2 )
            {
               case TypeCode::Int64:
                  return true;

               case TypeCode::Single:
                  return true;

               case TypeCode::Double:
                  return true;

               default:
                  return false;
            }
         }

         // Possible conversions from UInt64 follow. 
         if ( typeCode1 == TypeCode::UInt64 )
         {
            switch ( typeCode2 )
            {
               case TypeCode::Single:
                  return true;

               case TypeCode::Double:
                  return true;

               default:
                  return false;
            }
         }

         // Possible conversions from Int64 follow. 
         if ( typeCode1 == TypeCode::Int64 )
         {
            switch ( typeCode2 )
            {
               case TypeCode::Single:
                  return true;

               case TypeCode::Double:
                  return true;

               default:
                  return false;
            }
         }

         // Possible conversions from Single follow. 
         if ( typeCode1 == TypeCode::Single )
         {
            switch ( typeCode2 )
            {
               case TypeCode::Double:
                  return true;

               default:
                  return false;
            }
         }
      }

      return false;
   }

};

public ref class MyClass1
{
public:
   short myFieldB;
   int myFieldA;
   void MyMethod( long i, char k )
   {
      Console::WriteLine( "\nThis is MyMethod(long i, char k)" );
   }

   void MyMethod( long i, long j )
   {
      Console::WriteLine( "\nThis is MyMethod(long i, long j)" );
   }
};

int main()
{
   // Get the type of MyClass1.
   Type^ myType = MyClass1::typeid;

   // Get the instance of MyClass1.
   MyClass1^ myInstance = gcnew MyClass1;
   Console::WriteLine( "\nDisplaying the results of using the MyBinder binder.\n" );

   // Get the method information for MyMethod. 
   array<Type^>^types = {short::typeid,short::typeid};
   MethodInfo^ myMethod = myType->GetMethod( "MyMethod", static_cast<BindingFlags>(BindingFlags::Public | BindingFlags::Instance), gcnew MyBinder, types, nullptr );
   Console::WriteLine( myMethod );

   // Invoke MyMethod. 
   array<Object^>^obj = {32,32};
   myMethod->Invoke( myInstance, BindingFlags::InvokeMethod, gcnew MyBinder, obj, CultureInfo::CurrentCulture );
}

.NET Framework

Supported in: 4.6, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Supported in: 4, 3.5 SP1

Supported in: Windows Phone 8.1

Supported in: Windows Phone Silverlight 8.1

Supported in: Windows Phone Silverlight 8

Windows Phone 8.1, Windows Phone 8, Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Server Core Role not supported), Windows Server 2008 R2 (Server Core Role supported with SP1 or later; Itanium not supported)

The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

Was this page helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft