Partilhar via


Carregar dinamicamente e usando tipos

Reflexão fornece infra-estrutura usada pelos compiladores de linguagens, sistema autônomo Microsoft Visual Basic 2005 e JScript para implementar implícita associação tardia. Ligação é o processo de localizar a declaração (ou seja, a implementação) que corresponde a um tipo especificado com exclusividade.Quando esse processo ocorre em time de execução em vez de em time de compilar, ele é chamado de associação tardia.Visual Basic 2005 permite que você use implícita de vinculação tardia em seu código; o compilador do Visual Basic chama um método auxiliar que usa a reflexão para obter o tipo de objeto. Os argumentos passados para o método auxiliar com que o método apropriado ser chamado em time de execução.Esses argumentos são a instância (um objeto) na qual deseja chamar o método, o nome do método invocado (uma seqüência de caracteres) e os argumentos passados para o método chamado (uma matriz de objetos).

No exemplo a seguir, o compilador do Visual Basic usa reflexão implicitamente para chamar um método em um objeto cujo tipo não é conhecido no time de compilar.A HelloWorld classe possui um PrintHello método que imprime "Hello World" concatenadas com algum texto que é passado para oPrintHello método.The PrintHello método chamado neste exemplo é realmente um Type.InvokeMember; o código do Visual Basic permite que o PrintHello método ser chamado sistema autônomo se o tipo de objeto (helloObj) eram conhecido em time de compilar (associação inicial) em vez de em time de execução (associação tardia).

Imports System
Module Hello
    Sub Main()
        ' Sets up the variable.
        Dim helloObj As Object
        ' Creates the object.
        helloObj = new HelloWorld()
        ' Invokes the print method as if it was early bound
        ' even though it is really late bound.
        helloObj.PrintHello("Visual Basic Late Bound")
    End Sub
End Module

Ligação personalizada

Juntamente com o que está sendo usado implicitamente pelos compiladores para associação tardia, reflexão pode ser usado explicitamente no código para executar associação tardia.

The Common linguagem tempo de execução oferece suporte a várias linguagens de programação e as regras de ligação dessas linguagens são diferentes.No caso early limite, geradores de código podem controlar completamente essa ligação.No entanto, com associação tardia através de reflexão, ligação deve ser controlada por ligação personalizada.The Binder classe fornece controle personalizado do membro seleção e a chamada.

Usando a ligação personalizada, você pode carregar um assembly em time de execução, obter informações sobre tipos de assembly, especificar o tipo desejado e, em seguida, chamar métodos ou campos de acesso ou propriedades nesse tipo.Essa técnica é útil se você não souber o tipo de um objeto em time de compilar, sistema autônomo quando o tipo de objeto é dependente de entrada do usuário.

O exemplo a seguir demonstra um fichário personalizado simples, que não oferece nenhuma conversão de tipo de argumento.Código de Simple_Type.dll precede o principal exemplo. Certifique-se de criar Simple_Type.dll e inclua uma referência a ele o projeto no momento da compilação.

' Code for building Simple_Type.dll.
Imports System

Namespace Simple_Type
    Public Class MySimpleClass
        Public Overloads Sub MyMethod(ByVal str As String, 
            ByVal i As Integer)
            Console.WriteLine("MyMethod parameters: {0}, {1}", str, i)
        End Sub 'MyMethod

        Public Overloads Sub MyMethod(ByVal str As String, 
            ByVal i As Integer, ByVal j As Integer)
            Console.WriteLine("MyMethod parameters: {0}, {1}, {2}", str, 
                i, j)
        End Sub 'MyMethod
    End Class 'MySimpleClass
End Namespace 'Simple_Type

Imports System
Imports System.Reflection
Imports System.Globalization
Imports Simple_Type.Simple_Type

Namespace Custom_Binder
    Class MyMainClass
        Shared Sub Main()
            ' Get the type of MySimpleClass.
            Dim myType As Type = GetType(MySimpleClass)
            ' Get an instance of MySimpleClass.
            Dim myInstance As New MySimpleClass()
            Dim myCustomBinder As New MyCustomBinder()
            ' Get the method information for the overload being sought.
            Dim myMethod As MethodInfo = myType.GetMethod("MyMethod", 
                BindingFlags.Public Or BindingFlags.Instance, 
                    myCustomBinder, New Type() {GetType(String), 
                        GetType(Integer)}, Nothing)
            Console.WriteLine(myMethod.ToString())
            ' Invoke the overload.
            myType.InvokeMember("MyMethod", BindingFlags.InvokeMethod, 
                myCustomBinder, myInstance, 
                    New [Object]() {"Testing...", CInt(32)})
        End Sub 'Main
    End Class 'MyMainClass

    '****************************************************
    ' A simple custom binder that provides no
    ' argument type conversion.
    '****************************************************
    Class MyCustomBinder
        Inherits Binder

        Public Overrides Function BindToMethod(ByVal bindingAttr As 
            BindingFlags, ByVal match() As MethodBase, ByRef args() As 
                Object, ByVal modifiers() As ParameterModifier, ByVal 
                    culture As CultureInfo, ByVal names() As String, ByRef 
                        state As Object) As MethodBase
            If match Is Nothing Then
                Throw New ArgumentNullException("match")
            End If
            ' Arguments are not being reordered.
            state = Nothing
            ' Find a parameter match and return the first method with
            ' parameters that match the request.
            Dim mb As MethodBase
            For Each mb In match
                Dim parameters As ParameterInfo() = mb.GetParameters()
                If ParametersMatch(parameters, args) Then
                    Return mb
                End If
            Next mb
            Return Nothing
        End Function 'BindToMethod

        Public Overrides Function BindToField(ByVal bindingAttr As 
            BindingFlags, ByVal match() As FieldInfo, ByVal value As 
                Object, ByVal culture As CultureInfo) As FieldInfo
            If match Is Nothing Then
                Throw New ArgumentNullException("match")
            End If
            Dim fi As FieldInfo
            For Each fi In match
                If fi.GetType() Is value.GetType() Then
                    Return fi
                End If
            Next fi
            Return Nothing
        End Function 'BindToField

        Public Overrides Function SelectMethod(ByVal bindingAttr As 
            BindingFlags, ByVal match() As MethodBase, ByVal types() As 
                Type, ByVal modifiers() As ParameterModifier) As 
                    MethodBase
            If match Is Nothing Then
                Throw New ArgumentNullException("match")
            End If
            ' Find a parameter match and return the first method with
            ' parameters that match the request.
            Dim mb As MethodBase
            For Each mb In match
                Dim parameters As ParameterInfo() = mb.GetParameters()
                If ParametersMatch(parameters, types) Then
                    Return mb
                End If
            Next mb
            Return Nothing
        End Function 'SelectMethod

        Public Overrides Function SelectProperty(ByVal bindingAttr As 
            BindingFlags, ByVal match() As PropertyInfo, ByVal returnType 
                As Type, ByVal indexes() As Type, ByVal modifiers() As 
                    ParameterModifier) As PropertyInfo
            If match Is Nothing Then
                Throw New ArgumentNullException("match")
            End If
            Dim pi As PropertyInfo
            For Each pi In match
                If pi.GetType() Is returnType And 
                    ParametersMatch(pi.GetIndexParameters(), indexes) Then
                    Return pi
                End If
            Next pi
            Return Nothing
        End Function 'SelectProperty

        Public Overrides Function ChangeType(ByVal value As Object, 
            ByVal myChangeType As Type, ByVal culture As CultureInfo) 
                As Object
            Try
                Dim newType As Object
                newType = Convert.ChangeType(value, myChangeType)

                Return newType
                ' Throw an InvalidCastException if the conversion cannot
                ' be done by the Convert.ChangeType method.
            Catch
            End Try
        End Function 'ChangeType

        Public Overrides Sub ReorderArgumentArray(ByRef args() As Object, 
            ByVal state As Object)
            ' No operation is needed here because BindToMethod does not
            ' reorder the args array. The most common implementation
            ' of this method is shown below.
            
            ' ((BinderState)state).args.CopyTo(args, 0);
        End Sub 'ReorderArgumentArray

        ' Returns true only if the type of each object in a matches
        ' the type of each corresponding object in b.
        Private Overloads Function ParametersMatch(ByVal a() As 
            ParameterInfo, ByVal b() As Object) As Boolean
            If a.Length <> b.Length Then
                Return False
            End If
            Dim i As Integer
            For i = 0 To a.Length - 1
                If Not (a(i).ParameterType Is b(i).GetType()) Then
                    Return False
                End If
            Next i
            Return True
        End Function 'ParametersMatch

        ' Returns true only if the type of each object in a matches
        ' the type of each corresponding entry in b.
        Private Overloads Function ParametersMatch(ByVal a() As 
            ParameterInfo, ByVal b() As Type) As Boolean
            If a.Length <> b.Length Then
                Return False
            End If
            Dim i As Integer
            For i = 0 To a.Length - 1
                If Not (a(i).ParameterType Is b(i)) Then
                    Return False
                End If
            Next i
            Return True
        End Function 'ParametersMatch
    End Class 'MyCustomBinder
End Namespace 'Custom_Binder

// Code for building SimpleType.dll.
using System;

namespace Simple_Type
{
    public class MySimpleClass
    {
        public void MyMethod(string str, int i)
        {
            Console.WriteLine("MyMethod parameters: {0}, {1}", str, i);
        }

        public void MyMethod(string str, int i, int j)
        {
            Console.WriteLine("MyMethod parameters: {0}, {1}, {2}", 
                str, i, j);
        }
    }
}


using System;
using System.Reflection;
using System.Globalization;
using Simple_Type;
namespace Custom_Binder
{
    class MyMainClass
    {
        static void Main()
        {
            // Get the type of MySimpleClass.
            Type myType = typeof(MySimpleClass);

            // Get an instance of MySimpleClass.
            MySimpleClass myInstance = new MySimpleClass();
            MyCustomBinder myCustomBinder = new MyCustomBinder();

            // Get the method information for the particular overload 
            // being sought.
            MethodInfo myMethod = myType.GetMethod("MyMethod", 
                BindingFlags.Public | BindingFlags.Instance,
                myCustomBinder, new Type[] {typeof(string), 
                    typeof(int)}, null);
            Console.WriteLine(myMethod.ToString());
            
            // Invoke the overload.
            myType.InvokeMember("MyMethod", BindingFlags.InvokeMethod, 
                myCustomBinder, myInstance, 
                    new Object[] {"Testing...", (int)32});
        }
    }

    // ****************************************************
    //  A simple custom binder that provides no
    //  argument type conversion.
    // ****************************************************
    class MyCustomBinder : Binder
    {
        public override MethodBase BindToMethod(
            BindingFlags bindingAttr,
            MethodBase[] match,
            ref object[] args,
            ParameterModifier[] modifiers,
            CultureInfo culture,
            string[] names,
            out object state)
        {
            if(match == null)
                throw new ArgumentNullException("match");
            // Arguments are not being reordered.
            state = null;
            // Find a parameter match and return the first method with
            // parameters that match the request.
            foreach(MethodBase mb in match)
            {
                ParameterInfo[] parameters = mb.GetParameters();

                if(ParametersMatch(parameters, args))
                    return mb;
            }
            return null;
        }

        public override FieldInfo BindToField(BindingFlags bindingAttr, 
            FieldInfo[] match, object value, CultureInfo culture)
        {
            if(match == null)
                throw new ArgumentNullException("match");
            foreach(FieldInfo fi in match)
            {
                if(fi.GetType() == value.GetType())
                    return fi;
            }
            return null;
        }

        public override MethodBase SelectMethod(
            BindingFlags bindingAttr,
            MethodBase[] match,
            Type[] types,
            ParameterModifier[] modifiers)
        {
            if(match == null)
                throw new ArgumentNullException("match");

            // Find a parameter match and return the first method with
            // parameters that match the request.
            foreach(MethodBase mb in match)
            {
                ParameterInfo[] parameters = mb.GetParameters();
                if(ParametersMatch(parameters, types))
                    return mb;
            }

            return null;
        }

        public override PropertyInfo SelectProperty(
            BindingFlags bindingAttr,
            PropertyInfo[] match,
            Type returnType,
            Type[] indexes,
            ParameterModifier[] modifiers)
        {
            if(match == null)
                throw new ArgumentNullException("match");
            foreach(PropertyInfo pi in match)
            {
                if(pi.GetType() == returnType && 
                    ParametersMatch(pi.GetIndexParameters(), indexes))
                    return pi;
            }
            return null;
        }

        public override object ChangeType(
            object value,
            Type myChangeType,
            CultureInfo culture)
        {
            try
            {
                object newType;
                newType = Convert.ChangeType(value, myChangeType);
                return newType;
            }
            // Throw an InvalidCastException if the conversion cannot
            // be done by the Convert.ChangeType method.
            catch(InvalidCastException)
            {
                return null;
            }
        }

        public override void ReorderArgumentArray(ref object[] args, 
            object state)
        {
            // No operation is needed here because BindToMethod does not
            // reorder the args array. The most common implementation
            // of this method is shown below.
            
            // ((BinderState)state).args.CopyTo(args, 0);
        }

        // Returns true only if the type of each object in a matches
        // the type of each corresponding object in b.
        private bool ParametersMatch(ParameterInfo[] a, object[] b)
        {
            if(a.Length != b.Length)
                return false;
            for(int i = 0; i < a.Length; i++)
            {
                if(a[i].ParameterType != b[i].GetType())
                    return false;
            }
            return true;
        }

        // Returns true only if the type of each object in a matches
        // the type of each corresponding entry in b.
        private bool ParametersMatch(ParameterInfo[] a, Type[] b)
        {
            if(a.Length != b.Length)
                return false;
            for(int i = 0; i < a.Length; i++)
            {
                if(a[i].ParameterType != b[i])
                    return false;
            }
            return true;
        }
    }
}

InvokeMember e CreateInstance

Use Type.InvokeMember para invocar um membro de um tipo. The CreateInstance métodos para várias classes, sistema autônomo sistema.Activator and sistema.reflexão.Assembly, são formas especializadas de InvokeMember que cria novas instâncias do tipo especificado.The Fichário classe é usada para sobrecarga resolução e o argumento coerção esses métodos.

O exemplo a seguir mostra as três combinações possíveis de argumento coerção (conversão de tipo) e seleção de membro.Em caso 1, não é necessário nenhuma seleção de coerção ou membro do argumento.No caso de 2, é necessário somente a seleção de membro.No caso de 3, coerção de argumento só é necessária.

public class CustomBinderDriver
{
    public static void Main (string[] arguments)
    {
    Type t = typeof (CustomBinderDriver);
    CustomBinder binder = new CustomBinder();
    BindingFlags flags = BindingFlags.InvokeMethod|BindingFlags.Instance|
        BindingFlags.Public|BindingFlags.Static;

    // Case 1. Neither argument coercion nor member selection is needed.
    args = new Object[] {};
    t.InvokeMember ("PrintBob", flags, binder, null, args);

    // Case 2. Only member selection is needed.
    args = new Object[] {42};
    t.InvokeMember ("PrintValue", flags, binder, null, args);

    // Case 3. Only argument coercion is needed.
    args = new Object[] {"5.5"};
    t.InvokeMember ("PrintNumber", flags, binder, null, args);
    }

    public static void PrintBob ()
    {
        Console.WriteLine ("PrintBob");
    }

    public static void PrintValue (long value)
    {
        Console.WriteLine ("PrintValue ({0})", value);
    }
    public static void PrintValue (String value)
    {
        Console.WriteLine ("PrintValue\"{0}\")", value);
    }
   
    public static void PrintNumber (double value)
    {
        Console.WriteLine ("PrintNumber ({0})", value);
    }
}

Resolução de sobrecarga é necessária quando há mais de um membro com o mesmo nome.The Binder.BindToMethod e Binder.BindToField métodos são usados para resolver a ligação para um único membro. Binder.BindToMethod também fornece resolução de propriedade através de obter and conjunto acessadores de propriedade.

BindToMethod retorna o MethodBase para chamar, ou referência a um valor nulo ()Nada no Visual Basic) se não há tal invocação for possível.The MethodBase valor retornado não precisa ser uma dos contidos no correspondência parâmetro, embora esse seja o caso comum.

Quando ByRef argumentos estão presentes, o chamador convém recuperá-los.Portanto, Fichário permite que um cliente mapear a matriz de argumentos de volta ao formato original se BindToMethod tenha manipulado a matriz de argumentos.Para fazer isso, o chamador deve ser garantido que a ordem dos argumentos é inalterada.Quando os argumentos são passados por nome, Fichário reordena a matriz de argumento e que é o que vê o chamador.Para obter mais informações, consulte Binder.ReorderArgumentArray.

O conjunto de membros disponível são os membros definidos no tipo ou em qualquer tipo de base.If BindingFlags.NonPublic for especificado, membros de qualquer acessibilidade serão retornados no conjunto.If BindingFlags.NonPublic não for especificado, o fichário deve impor regras de acessibilidade.Ao especificar o Público or NonPublic sinalizar de vinculação, você também deve especificar o Instância or Estáticosinalizar de ligação de ou nenhum membro será retornado.

Se houver apenas um membro do nome fornecido, não é necessário nenhum retorno de chamada e ligação é feita no método.Caso 1 do código de exemplo ilustra este ponto: Somente um PrintBob método está disponível e, portanto, não é necessário nenhum retorno de chamada.

Se houver mais de um membro do conjunto disponível, todos esses métodos são passados para BindToMethod, que seleciona o método apropriado e o retorna.No caso de 2 do exemplo de código, há dois métodos chamados PrintValue.O método apropriado é selecionado por telefonar BindToMethod.

ChangeType executa a coerção argumento (conversão de tipo), que converte os argumentos real para o tipo dos argumentos formais do método selecionado. ChangeType é chamado para cada argumento, mesmo se os tipos de correspondem exata.

No caso de 3 do código de exemplo, um argumento real do tipo Seqüência de caracteres com um valor de "5.5" é passado para um método com um argumento formal do tipo Duplo.Para a invocação seja bem-sucedida, o valor de seqüência de caracteres "5.5" deve ser convertido em um valor duplo.ChangeType executa esta conversão.

ChangeType executa somente sem perdas ou alargamento coercions, sistema autônomo mostrado na tabela seguinte.

Tipo de fonte

Tipo de destino

Qualquer tipo

Seu tipo de base

Qualquer tipo

Interface ele implementa

Char

UInt16, UInt32, Int32, UInt64, Int64, único, duplo

Byte

Char, UInt16, Int16, UInt32, Int32, UInt64, Int64, único, duplo

SByte

Int16, Int32, Int64, único, duplo

UInt16

UInt32, Int32, UInt64, Int64, único, duplo

Int16

Int32, Int64, único, duplo

UInt32

UInt64, Int64, único, duplo

Int32

Int64, Single, dupla

UInt64

Único, duplo

Int64

Único, duplo

Single

Double

Tipo nonreference

Tipo de referência

The Type classe possui Obter métodos que usam parâmetros de tipo Fichário para resolver referências a um determinado membro.Type.GetConstructor, Type.GetMethod, e Type.GetProperty Pesquisar por um determinado membro do tipo corrente, fornecendo informações de assinatura para esse membro. Binder.SelectMethod e Binder.SelectProperty são chamados de volta em para selecionar as informações de assinatura de determinado dos métodos apropriados.

Consulte também

Conceitos

Exibindo informações de tipo

Conversão: Visão geral

Referência

Type.InvokeMember

Assembly.Load