Udostępnij za pośrednictwem


Odbicie (C++/CLI)

Odbicie zezwala na typy danych znanych inspekcji w czasie wykonywania.Odbicie umożliwia wyliczenie typów danych w danym zestawie, a członkowie danego typu klasy lub wartości, które mogą zostać odnalezione.Jest to prawdą niezależnie od tego, czy typ został znany lub określany w czasie kompilacji.Dzięki temu odbicie użyteczna dla rozwoju i narzędzia do zarządzania kodem.

Należy zauważyć, że podana nazwa zestawu jest silna nazwa (zobacz Strong-Named zestawy), który zawiera wersję zestawu, kultury i informacje o podpisywaniu.Należy zauważyć, że nazwę obszaru nazw, w którym zdefiniowano typ danych mogą być pobierane, wraz z nazwą klasy podstawowej.

Najczęstszym sposobem uzyskania dostępu do funkcji odbicia jest przez GetType metody.Ta metoda jest świadczone przez System::Object, z którego wywodzą wszystkich klas zebrane śmieci.

Rozważania na temat .exe zbudowany z kompilatorem Visual C++ jest dozwolone, jeśli .exe jest zbudowany z /clr:pure lub /clr:safe opcje kompilatora.Aby uzyskać więcej informacji, zobacz /clr (Kompilacja środowiska uruchomieniowego języka wspólnego).

Tematy w tej sekcji:

Aby uzyskać więcej informacji, zobacz System.Reflection nazw

Przykład

GetType Metoda zwraca wskaźnik do Type klasy obiektu, który opisuje typ na kiedy obiekt jest oparty. ( Typu obiekt nie zawiera żadnych informacji specyficznych dla instancji.) Jednym z tych elementów jest pełną nazwę typu, które mogą być wyświetlane w następujący sposób:

Należy zauważyć, że nazwa typu zawiera pełnego zakresu, w którym zdefiniowano typu, w tym obszarze nazw, i który jest wyświetlany w .NET składni z kropką jako operator zakres rozpoznawania.

// 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());
}
  

Typy wartości mogą być używane z GetType jak również działać, ale muszą być zapakowane po raz pierwszy.

// 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());
}
  

Podobnie jak w przypadku GetType metoda, TypeID operator zwraca wskaźnik do typu obiektu, więc ten kod wskazuje nazwę typu System.Int32.Wyświetlanie nazw typu jest najbardziej podstawowa funkcja odbicia, ale potencjalnie bardziej użyteczną techniką jest sprawdzać lub Odkryj prawidłowe wartości dla typy wyliczane.Można to zrobić przy użyciu statycznego Enum::GetNames funkcja, która zwraca tablicę ciągów, każda zawierająca wartość wyliczenia w postaci tekstu. Poniższy przykład pobiera tablicę ciągów, które opisuje wartości wyliczenia wartości dla Opcje enum (CLR) i wyświetla je w pętli.

Jeśli opcja czwartym dodaje się do Opcje wyliczenie, ten kod będzie zgłaszał nowa opcja bez ponownej kompilacji, nawet jeśli wyliczenie jest zdefiniowany w oddzielnych zestawów.

// 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);
}
  

GetType Obiekt obsługuje szereg elementów członkowskich i właściwości, które mogą służyć do zbadania typu.Ten kod pobiera i wyświetla niektóre z tych informacji:

// 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);
}
  

Odbicie pozwala również wyliczenie typów w zestawie i członków w klasach.Do wykazania tej funkcji, należy zdefiniować prostą klasę:

// 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; }
   }
};

Jeśli powyższy kod jest kompilowany do biblioteki DLL o nazwie vcpp_reflection_6.dll, można następnie użyć odbicie na sprawdzenie zawartości tego zestawu.Wiąże się to przy użyciu statycznego odbicia funkcji API Assembly::Load załadować zestawu.Ta funkcja zwraca adres zestawu obiekt, które następnie mogą być wyszukiwane o moduły i typów w obrębie.

Po system odbicie pomyślnie ładuje montaż, tablica typu obiekty są pobierane z Assembly::GetTypes funkcji.Każdy element tablicy zawiera informacje o innego typu, mimo że w tym przypadku tylko jedna klasa jest zdefiniowana.Za pomocą pętli, każdy typu w tej tablicy jest kwerendy o elementy członkowskie typu za pomocą Type::GetMembers funkcji.Ta funkcja zwraca tablicę obiektu MethodInfo obiektów, każdy obiekt zawierający informacje na temat funkcji członka, członek danych lub właściwość typu.

Uwaga na liście metod jawnie zawiera funkcje zdefiniowane w KlasaTestowa i funkcje niejawnie dziedziczone z System::Object klasy.Jako część opisywanego .NET, a nie w składni języka Visual C++ właściwości są wyświetlane jako podstawowego elementu danych dostępne przez funkcje get/set.Funkcje get/set pojawiają się na tej liście jako metody regularnych.Odbicie jest obsługiwane za pośrednictwem common language runtime nie przez kompilator języka Visual C++.

Mimo, że ten kod jest używany do kontroli zdefiniowanego zestawu, przypadku użycia tego kodu do wglądu zestawów .NET.Na przykład jeśli zmienisz TestAssembly mscorlib, następnie zobaczysz aukcji każdego typu i metody zdefiniowane w 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);
}

Zobacz też

Inne zasoby

Programowanie .NET w programie Visual C++