Compartilhar via


Reflexão (C + + / CLI)

Reflexo permite tipos de dados conhecidos ser inspecionado em tempo de execução.Reflexão permite a enumeração de tipos de dados em um determinado assembly e os membros de um determinado tipo de classe ou valor que podem ser descobertos.Isso é verdadeiro independentemente do tipo foi conhecido ou referenciado em tempo de compilação.Isso torna reflexo um recurso útil para desenvolvimento e ferramentas de gerenciamento de código.

Observe que o nome do assembly fornecido é o nome forte (consulte Strong-Named Assemblies), que inclui a versão do assembly, cultura e informações de assinatura.Observe também que o nome do namespace no qual é definido o tipo de dados pode ser recuperado, juntamente com o nome da classe base.

É a maneira mais comum para acessar recursos de reflexão por meio de GetType método.Este método é fornecido por System::Object, da qual derivam todas as classes de coleta de lixo.

Reflexão em um. exe criado com o compilador Visual C++ é permitido se o. exe é construído com o /clr:pure ou /clr:safe opções do compilador.Consulte /CLR (common Language Runtime Compilation) para maiores informações.

Tópicos nesta seção:

Para obter mais informações, consulte Namespace System. Reflection

Exemplo

O GetType método retorna um ponteiro para um Type o objeto de classe, que descreve o tipo após quando o objeto se baseia.(O tipo objeto não contém qualquer informação específica de instância.) Um desses itens é o nome completo do tipo, pode ser exibido da seguinte maneira:

Observe que o nome de tipo inclui o escopo completo no qual o tipo é definido, incluindo o namespace, e que é exibido na.NET sintaxe com um ponto como o operador de resolução de escopo.

// vcpp_reflection.cpp
// compile with: /clr
using namespace System;
int main() {
   String ^ s = "sample string";
   Console::WriteLine("full type name of '{0}' is '{1}'", s, s->GetType());
}
  

Tipos de valor podem ser usados com o GetType funcionar bem, mas deve ser box primeiro.

// vcpp_reflection_2.cpp
// compile with: /clr
using namespace System;
int main() {
   Int32 i = 100; 
   Object ^ o = i;
   Console::WriteLine("type of i = '{0}'", o->GetType());
}
  

Como com o GetType método, o typeid (Extensões de Componentes C++) operador retorna um ponteiro para um tipo object, portanto, este código indica o nome do tipo Int32.Exibindo nomes de tipo é o recurso mais básico de reflexão, mas uma técnica potencialmente mais útil é inspecionar ou descobrir os valores válidos para tipos enumerados.Isso pode ser feito usando o estático Enum::GetNames função, que retorna uma matriz de seqüências de caracteres, cada uma contendo um valor de enumeração na forma de texto.O exemplo a seguir recupera uma matriz de seqüências de caracteres que descreve os valores de enumeração de valor para o Opções enum (CLR) e os exibe em um loop.

Se uma quarta opção é adicionada para o Opções enumeração, esse código relatará a nova opção sem recompilação, mesmo se a enumeração é definida em um assembly separado.

// vcpp_reflection_3.cpp
// compile with: /clr
using namespace System;

enum class Options {   // not a native enum
   Option1, Option2, Option3
};

int main() {
   array<String^>^ names = Enum::GetNames(Options::typeid);

   Console::WriteLine("there are {0} options in enum '{1}'", 
               names->Length, Options::typeid);

   for (int i = 0 ; i < names->Length ; i++)
      Console::WriteLine("{0}: {1}", i, names[i]);

   Options o = Options::Option2;
   Console::WriteLine("value of 'o' is {0}", o);
}
  

O GetType objeto oferece suporte a um número de membros e propriedades que podem ser usadas para examinar um tipo.Este código recupera e exibe algumas informações:

// vcpp_reflection_4.cpp
// compile with: /clr
using namespace System;
int main() {
   Console::WriteLine("type information for 'String':");
   Type ^ t = String::typeid;

   String ^ assemblyName = t->Assembly->FullName;
   Console::WriteLine("assembly name: {0}", assemblyName);

   String ^ nameSpace = t->Namespace;
   Console::WriteLine("namespace: {0}", nameSpace);

   String ^ baseType = t->BaseType->FullName;
   Console::WriteLine("base type: {0}", baseType);

   bool isArray = t->IsArray;
   Console::WriteLine("is array: {0}", isArray);

   bool isClass = t->IsClass;
   Console::WriteLine("is class: {0}", isClass);
}
  

Reflexão também permite a enumeração de tipos em um assembly e os membros dentro de classes.Para demonstrar esse recurso, defina uma classe simples:

// vcpp_reflection_5.cpp
// compile with: /clr /LD
using namespace System;
public ref class TestClass {
   int m_i;
public:
   TestClass() {}
   void SimpleTestMember1() {}
   String ^ SimpleMember2(String ^ s) { return s; } 
   int TestMember(int i) { return i; }
   property int Member {
      int get() { return m_i; }
      void set(int i) { m_i = i; }
   }
};

Se o código acima é compilado em uma DLL chamada vcpp_reflection_6.dll, você pode usar reflexão para inspecionar o conteúdo desse assembly.Isso envolve usando a função API de reflexão estática Assembly::Load para carregar o assembly.Esta função retorna o endereço de um Assembly objeto que pode ser consultado sobre módulos e tipos dentro.

Assim que o sistema de reflexão carrega com êxito o assembly, uma matriz de tipo objetos é recuperada com o Assembly::GetTypes função.Cada elemento da matriz contém informações sobre um tipo diferente, embora nesse caso, apenas uma classe é definida.Usando um loop, cada tipo nessa matriz é consultado sobre os membros de tipo usando o Type::GetMembers função.Esta função retorna uma matriz de MethodInfo objetos, cada objeto que contém informações sobre a função de membro, membro de dados ou propriedade no tipo.

Observe que a lista de métodos inclui as funções explicitamente definidas no TestClass e as funções implicitamente herdadas do System::Object classe.Como parte do que está sendo descrito.NET em vez de na sintaxe do Visual C++, as propriedades aparecem como o membro de dados subjacentes acessado por funções get/set.As funções get/set aparecem nesta lista como métodos regulares.Reflexão é suportado através do common language runtime, não pelo compilador do Visual C++.

Embora usado esse código para inspecionar um assembly que você definiu, você também pode usar esse código para inspecionar.NET assemblies.Por exemplo, se você alterar TestAssembly para mscorlib, você verá uma lista de cada tipo e o método definido no mscorlib. dll.

// vcpp_reflection_6.cpp
// compile with: /clr
using namespace System;
using namespace System::IO;
using namespace System::Reflection;
int main() {
   Assembly ^ a = nullptr;
   try {
      // load assembly -- do not use file extension
      // will look for .dll extension first
      // then .exe with the filename
      a = Assembly::Load("vcpp_reflection_5");
   }
   catch (FileNotFoundException ^ e) {
      Console::WriteLine(e->Message);
      return -1;
   }

   Console::WriteLine("assembly info:");
   Console::WriteLine(a->FullName);
   array<Type^>^ typeArray = a->GetTypes();

   Console::WriteLine("type info ({0} types):", typeArray->Length);

   int totalTypes = 0;
   int totalMembers = 0;
   for (int i = 0 ; i < typeArray->Length ; i++) {
      // retrieve array of member descriptions
      array<MemberInfo^>^ member = typeArray[i]->GetMembers();

      Console::WriteLine("  members of {0} ({1} members):", 
      typeArray[i]->FullName, member->Length);
      for (int j = 0 ; j < member->Length ; j++) {
         Console::Write("       ({0})", 
         member[j]->MemberType.ToString() );
         Console::Write("{0}  ", member[j]);
         Console::WriteLine("");
         totalMembers++;
      }
      totalTypes++;
   }
   Console::WriteLine("{0} total types, {1} total members",
   totalTypes, totalMembers);
}

Consulte também

Outros recursos

.NET programação no Visual C++