Odbicie (C + +/ CLI)
Odbicie umożliwia znanych typów podlegających inspekcji w czasie wykonywania.Odbicie umożliwia wyliczenie typów danych w danym zestawie i może być wykrywany członków danego typu klasy lub wartość.Jest to prawdą niezależnie od tego, czy znane lub odwołania w czasie kompilacji typu.Dzięki temu odbicie użyteczną funkcję dla rozwoju i narzędzia do zarządzania kodem.
Zauważ, że nazwa zestawu, pod warunkiem silnej nazwy (zobacz Zestawy Strong-Named), która obejmuje wersji zestawu, kultury i informacje o podpisywaniu.Należy również zauważyć, że nazwa obszaru nazw, w której określony jest typ danych mogą być pobierane, wraz z nazwą klasy bazowej.
Najczęstszym sposobem dostępu do funkcji odbicia jest poprzez GetType metody.Metoda ta jest dostarczana przez System::Object, od uzyskania wszystkich klas zebrane garbage.
Rozważania na temat pliku .exe, zbudowany z kompilatorem Visual C++ jest dozwolone, jeżeli exe jest zbudowany z /clr:pure lub /clr:safe opcje kompilatora.Zobacz / CLR (kompilacja wspólnej Language Runtime) Aby uzyskać więcej informacji.
Tematy w tej sekcji:
Jak: wdrożenie architektury składnika dodatku typu Plug-In, przy użyciu odbicia (C + +/ CLI)
Jak: wyliczyć typów danych w zestawach przy użyciu odbicia (C + +/ CLI)
Aby uzyskać więcej informacji, zobacz System.Reflection obszaru nazw.
Przykład
GetType Metoda zwraca wskaźnik do Type obiektu klasy, która opisuje typ, podczas gdy obiekt jest oparty.( Typu obiekt nie zawiera żadnych informacji specyficznych dla instancji.) Jeden element taki jest pełna nazwa typu, które mogą być wyświetlane w następujący sposób:
Należy zauważyć, że nazwa typu obejmuje pełny zakres, w której określony jest typ, łącznie z obszaru nazw i że jest wyświetlana w.NET składni z kropką jako operator zakres rozdzielczości.
// 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, może być używany z GetType jak również działać, ale musi być najpierw ramkach.
// 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());
}
Tak jak w GetType metody, typeid (C++ Component Extensions) 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 jest potencjalnie bardziej użyteczne techniki inspekcji lub odkryć prawidłowe wartości typy wyliczane.Można to zrobić przy użyciu statycznego Enum::GetNames działa, 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 opisano wartości wyliczenia wartości Opcje enum (CLR) i wyświetla je w pętli.
Jeśli opcja czwartym dodaje się Opcje wyliczenia, ten kod będzie sprawozdanie nowa opcja bez ponownej kompilacji, nawet jeśli wyliczenie jest zdefiniowany w oddzielnych zestawu.
// 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 liczba członków i właściwości, które mogą być używane do zbadania typu.Ten kod pobiera i wyświetla niektóre informacje:
// 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 umożliwia również wyliczanie typów w zestawie i członków w klasach.Do wykazania tej funkcji, można 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ższe kodu jest skompilowany w DLL, o nazwie vcpp_reflection_6.dll, następnie umożliwia odbicie zbadać zawartość tego zestawu.Obejmuje to za pomocą statycznych odbicie funkcji API Assembly::Load ładowania zestawu.Ta funkcja zwraca adres zestawu obiekt, który można przeszukiwać o moduły i typów w obrębie.
Po system odbicie pomyślnie ładuje zgromadzenie tablicę typu obiektów jest pobierana z Assembly::GetTypes funkcji.Każdy element tablicy zawiera informacji na temat różnych typów, chociaż w tym przypadku jest zdefiniowany tylko jedną klasę.Za pomocą pętli, każdy typu w tej tablicy proszeni o elementy typu za pomocą Type::GetMembers funkcji.Ta funkcja zwraca tablicę obiektu MethodInfo obiektów, każdy obiekt zawierający informacje na temat funkcji składowej, elementu danych lub właściwość typu.
Uwaga lista metod jawnie zawiera funkcje zdefiniowane w KlasaTestowa i funkcje niejawnie dziedziczone z System::Object klasy.Jak są opisane w części.NET, zamiast w składni języka Visual C++ właściwości pojawiają się jako członek danych podstawowych, dostęp do funkcji get i set.Funkcje get i set wyświetlany na liście jako metody regularnych.Odbicia jest obsługiwane za pośrednictwem common language runtime nie przez kompilator Visual C++.
Mimo że ten kod jest używany do przeprowadzania inspekcji zdefiniowanego zestawu, przypadku użycia tego kodu do inspekcji.Zestawy netto.Na przykład jeśli zmienisz TestAssembly mscorlib, następnie zobaczysz aukcji każdego rodzaju 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);
}