1. Was ist Reflexion:
Reflexion, chinesische Übersetzung ist Reflexion.
Auf diese Weise erhalten Sie Laufzeittypinformationen in .Net. .Net-Anwendungen bestehen aus mehreren Teilen: „Assembly“, „Modul“, „Typ“ und Reflection bietet eine Programmiermethode, die es Programmierern ermöglicht, relevante Informationen zu erhalten über diese Komponenten während der Programmausführung.
Ein Überblick über Reflexion
Definition von Reflexion: Die Fähigkeit, Metadaten zu untersuchen und Typinformationen darüber zu sammeln. Metadaten (die grundlegendste Dateneinheit nach der Kompilierung) sind eine große Anzahl von Tabellen. Beim Kompilieren einer Assembly oder eines Moduls erstellt der Compiler eine Klassendefinitionstabelle, eine Felddefinitionstabelle, eine Methodendefinitionstabelle usw. Der System.reflection-Namespace enthält mehrere Klassen, mit denen Sie den Code dieser Metadatentabellen widerspiegeln (analysieren) können.
2. Spezifische Verwendungszwecke von Reflection:
(1) Verwenden Sie Assembly, um Assemblys zu definieren und zu laden, laden Sie im Assembly-Manifest aufgeführte Module und suchen Sie a Typ aus dieser Assembly und erstellen Sie eine Instanz dieses Typs.
(2) Verwenden Sie „Module“, um die Assembly zu verstehen, die das Modul und die Klassen im Modul enthält. Sie können auch alle globalen Methoden oder andere spezifische nicht-globale Methoden abrufen, die im Modul definiert sind.
(3) Verwenden Sie ConstructorInfo, um den Namen, die Parameter, Zugriffsmodifikatoren (z. B. pulic oder privat) und Implementierungsdetails (z. B. abstrakt oder virtuell) des Konstruktors zu erfahren. Verwenden Sie die GetConstructors- oder GetConstructor-Methode des Typs, um einen bestimmten Konstruktor aufzurufen.
(4) Verwenden Sie MethodInfo, um den Namen der Methode, den Rückgabetyp, die Parameter, Zugriffsmodifikatoren (z. B. pulic oder privat) und Implementierungsdetails (z. B. abstrakt oder virtuell) usw. zu verstehen. Verwenden Sie die GetMethods- oder GetMethod-Methode des Typs, um eine bestimmte Methode aufzurufen.
(5) Verwenden Sie FiedInfo, um den Namen des Felds zu verstehen, auf Modifikatoren (z. B. öffentlich oder privat) und Implementierungsdetails (z. B. statisch) usw. zuzugreifen und den Feldwert abzurufen oder festzulegen.
(6) Verwenden Sie EventInfo, um den Namen des Ereignisses, den Datentyp des Ereignishandlers, benutzerdefinierte Eigenschaften, Deklarationstyp und Reflexionstyp usw. zu erfahren und Ereignishandler hinzuzufügen oder zu entfernen.
(7) Verwenden Sie PropertyInfo, um den Namen, den Datentyp, den Deklarationstyp, den Reflexionstyp, den schreibgeschützten oder beschreibbaren Status des Attributs usw. zu verstehen und den Attributwert abzurufen oder festzulegen.
(8) Verwenden Sie ParameterInfo, um den Parameternamen, den Datentyp, ob es sich um einen Eingabeparameter oder einen Ausgabeparameter handelt, sowie die Position des Parameters in der Methodensignatur usw. zu verstehen.
3. Namespace im Zusammenhang mit Reflection:
System.Reflection.Assembly
System.Reflection.MemberInfo
System.Reflection.EventInfo
System.Reflection.FieldInfo
System.Reflection.MethodBase
System.Reflection.ConstructorInfo
System.Reflection.MethodInfo
System.Reflection.PropertyInfo
System.Type
4. Hierarchisches Reflexionsmodell:
Hinweis: Es gibt eine Eins-zu-viele-Beziehung zwischen den Ebenen
Die Rolle der Reflexion:
1. Sie können Reflektion verwenden, um dynamisch Instanzen eines Typs zu erstellen, den Typ an ein vorhandenes Objekt zu binden oder den Typ von einem vorhandenen Objekt abzurufen
2. Die Anwendung muss zur Laufzeit einen bestimmten Typ aus einer bestimmten Assembly laden, damit Reflektion zum Erreichen einer bestimmten Aufgabe verwendet werden kann.
3. Reflection wird hauptsächlich bei Klassenbibliotheken verwendet. Diese Klassenbibliotheken müssen die Definition eines Typs kennen, um mehr Funktionen bereitzustellen.
Anwendungspunkte:
1. In realen Anwendungen gibt es nur wenige Anwendungen, die Reflexionstypen verwenden müssen
2. Die Verwendung der dynamischen Reflexionsbindung erfordert Leistungseinbußen
3. Einige Metadateninformationen können nicht durch Reflexion abgerufen werden
4. Bestimmte Reflexionstypen sind speziell für die Verwendung durch diejenigen konzipiert, die Compiler für die CLR entwickeln. Sie sollten sich daher darüber im Klaren sein, dass nicht alle Reflexionstypen für jeden geeignet sind.
6. Praktische Anwendung der Reflexion:
appDomain 어셈블리 반영
static void Main
{
// GetAssemblies를 통해 appDomain의 모든 어셈블리 호출
foreach(Appdomain.currentDomain.GetAssemblies()의 어셈블리 어셈블리)
{
//현재 어셈블리의 정보 반영
reflector.ReflectOnAssembly(assem)
}
}
참고: AppDomain 개체의 GetAssemblies 메서드를 호출하면 다음이 반환됩니다. a System.Reflection.Assembly 요소로 구성된 배열입니다.
단일 어셈블리 반영
system.reflecton.assemble 유형은 다음 세 가지 메서드를 제공합니다.
1. 로드 방법: 매우 권장되는 방법입니다. 로드 방법은 CLR이 전역 어셈블리 버퍼, 애플리케이션 기본 디렉터리 및 개인 경로에 정책을 적용하도록 합니다. 어셈블리를 검색합니다. 어셈블리를 찾을 수 없으면 시스템에서 예외가 발생합니다.
2. LoadFrom 메서드: 어셈블리 파일의 경로 이름(확장자 포함)을 전달하면 CLR은 사용자가 지정한 어셈블리를 로드합니다. 전달된 매개 변수에는 버전 번호, 문화권 및 공개 키 정보가 포함될 수 없습니다. 지정된 경로에서 발견되면 예외가 발생합니다.
3. LoadWithPartialName: 애플리케이션이 로드되는 어셈블리 버전을 확인할 수 없으므로 이 메서드를 사용하지 마세요. 이 방법의 유일한 목적은 .Net 프레임워크의 테스트 단계에서 .Net 프레임워크가 제공하는 특정 동작을 사용하는 고객을 돕는 것이며, 이 방법은 결국 폐기될 것입니다.
참고: system.AppDomain은 Assembly의 정적 Load 메서드와 다른 Load 메서드도 제공합니다. AppDomain의 로드 메서드는 인스턴스 메서드이며 어셈블리에 대한 참조를 반환합니다. Assembly의 정적 Load 메서드 Fangfa는 어셈블리를 값으로 캡슐화하여 보냅니다. AppDomain의 로드 메서드를 사용하지 마세요.
유형 정보를 얻기 위해 리플렉션을 사용하세요.
유형 정보를 얻기 위해 리플렉션을 사용하는 간단한 예 :
시스템 사용;
sytem.reflection 사용;
클래스 반영
{
static void Main(string[]args)
{
reflecting Reflect=new Reflecting();// 새로운 자체 클래스 정의
//reflecting.exe 어셈블리 호출
어셈블리 myAssembly =assembly.loadfrom(“reflecting.exe”)
reflect.getreflectioninfo(myAssembly); // 리플렉션 정보 가져오기
}
// 리플렉션 콘텐츠를 가져오는 메서드 정의
void getreflectioninfo(assemble myassemble)
{
type[] typearr=myassemby.Gettypes();// 유형 가져오기
foreach(type typearr에 입력)//각 유형에 대한 세부 정보 가져오기
{
//유형의 구조 정보 가져오기
constructorinfo[] myconstructors=type.GetConstructors;
// 유형 필드 정보 가져오기
fieldinfo[] myfields=type.GetFiedls()
//메서드 정보 가져오기
MethodInfo myMethodInfo=type.GetMethods();
// 속성 정보 가져오기
propertyInfo[] myproperties=type. GetProperties
//이벤트 정보 가져오기
EventInfo[] Myevents=type.GetEvents;
}
}
}
기타 유형 개체를 가져오는 방법:
1. System.type 매개 변수는 문자열 유형이며 문자열은 해당 유형의 전체 이름(해당 네임스페이스 포함)을 지정해야 합니다
2. System.type은 GetNestedType, GetNestedTypes
3의 두 가지 인스턴스 메서드를 제공합니다. Syetem.Reflection.Assembly 유형에서 제공하는 인스턴스 메서드는 GetType, GetTypes, GetExporedTypes
4입니다. System.Reflection.Moudle은 다음과 같은 인스턴스 메서드를 제공합니다. GetType, GetTypes, FindTypes
반사 유형의 멤버 설정
반사 유형의 멤버는 반사 계층 구조에서 가장 낮은 데이터 계층입니다. 모델. 유형 개체의 GetMembers 메서드를 통해 유형의 멤버를 얻을 수 있습니다. 매개 변수 없이 GetMembers를 사용하는 경우 공개적으로 정의된 정적 변수와 해당 유형의 인스턴스 멤버만 반환합니다. 또한 매개 변수와 함께 GetMembers를 사용하여 매개 변수 설정을 통해 지정된 유형 멤버를 반환할 수도 있습니다. 특정 매개변수에 대해서는 msdn의 system.reflection.bindingflags 열거 유형에 대한 자세한 설명을 참조하세요.
예:
//반환할 유형의 멤버 콘텐츠 설정
bindingFlags bf=bingdingFlags.DeclaredOnly|bingdingFlags.Nonpublic|BingdingFlags.Public;
foreach( MemberInfo mi int t.getmembers(bf))
{
writeline(mi.membertype) //지정된 타입 멤버 출력
}
리플렉션을 통해 해당 타입의 인스턴스 생성
Pass Reflection은 어셈블리의 유형을 얻을 수 있으며, 얻은 어셈블리 유형을 기반으로 해당 유형의 새 인스턴스를 생성할 수 있습니다. 이는 앞서 언급한 런타임 바인딩을 구현하기 위해 런타임에 객체를 생성하는 기능이기도 합니다. 다음 방법을 통해 이를 달성할 수 있습니다.
1. System.Activator의 CreateInstance 메서드입니다. 이 메서드는 새 개체에 대한 참조를 반환합니다.
2. System.Activator의 createInstanceFrom은 이전 메서드와 비슷하지만 유형과 해당 어셈블리를 지정해야 합니다.
3. System.Appdomain 메서드: createInstance, CreateInstanceAndUnwrap, CreateInstranceFrom 및 CreateInstraceFromAndUnwrap
4. System.type의 InvokeMember 인스턴스 메서드: 이 메서드는 전달된 매개 변수와 일치하는 생성자를 반환하고 형식을 구성합니다.
5. System.reflection.constructinfo의 인스턴스 메소드 호출
리플렉션 유형 인터페이스
특정 유형으로 상속된 모든 인터페이스의 컬렉션을 가져오려면 FindInterfaces GetInterface 또는 GetInterfaces of Type을 호출하면 됩니다. 이러한 모든 메서드는 형식이 직접 상속하는 인터페이스만 반환할 수 있으며 인터페이스에서 상속되는 인터페이스는 반환하지 않습니다. 인터페이스의 기본 인터페이스를 반환하려면 위 메서드를 다시 호출해야 합니다.
리플렉션 성능
리플렉션 중에 CLR은 매개변수 확인, 권한 확인 등 더 많은 작업을 수행해야 하며 속도가 매우 느립니다. 프로그래밍 시 리플렉션을 사용하지 마세요. 동적으로 생성된 유형(후기 바인딩)을 작성하려는 애플리케이션의 경우 다음 방법을 대신 사용할 수 있습니다.
1. 클래스 상속을 통해. 컴파일 시간에 알려진 기본 유형에서 유형을 파생시키고, 런타임 시 유형의 인스턴스를 생성하고, 기본 유형의 변수에 해당 유형에 대한 참조를 넣은 다음, 기본 유형의 가상 메서드를 호출합니다.
2. 인터페이스를 통해 구현됩니다. 런타임 시 해당 유형의 인스턴스를 생성하고 해당 인터페이스 유형의 변수에 해당 인스턴스에 대한 참조를 배치한 다음 인터페이스에서 정의된 가상 메서드를 호출합니다.
3. 위임을 통해 달성됩니다. 이름과 프로토타입이 컴파일 타임에 알려진 대리자와 일치하는 메서드를 형식이 구현하도록 합니다. 먼저 런타임에 이 형식의 인스턴스를 생성한 다음 개체와 메서드 이름을 사용하여 대리자의 인스턴스를 생성한 다음 대리자를 통해 원하는 메서드를 호출합니다. 이 방법은 더 많은 작업이 필요하며 이전 두 가지 방법보다 효율성이 떨어집니다.
사용 참고 사항:
1. 크로스 어셈블리 리플렉션
개발 중에는 A.dll에서 리플렉션 B가 필요한 경우가 많습니다. dll의 유형에 주의를 기울이면 런타임 오류가 발생합니다. 크로스 어셈블리 리플렉션과 관련하여 다음 두 가지 사항을 기억하세요.
(1) typeof를 사용하고 컴파일이 통과할 수 있으면 크로스 어셈블리 리플렉션이 정상적으로 실행되어야 합니다. typeof는 강력한 타이핑을 지원한다고 할 수 있습니다. 예를 들어
Type supType = typeof(EnterpriseServerBase.DataAccess.IDBAccesser);
현재 어셈블리가 EnterpriseServerBase.dll에 대한 참조를 추가하지 않으면 컴파일 시 오류가 보고됩니다.
(2) Type.GetType을 사용하는 경우 Type.GetType이 강력한 형식이 아니기 때문에 상황이 더 복잡해집니다. Type.GetType의 매개 변수는 문자열입니다. string으로 표시되는 대상 유형이 현재 어셈블리에 없으면 Type.GetType은 런타임에 null을 반환합니다. 해결 방법은 대상 어셈블리를 먼저 로드한 다음 Assembly.GetType 메서드를 사용하는 것입니다. 예:
Assembly asmb = Assembly.LoadFrom("EnterpriseServerBase.dll") ;
Type supType = asmb.GetType("EnterpriseServerBase.DataAccess.IDBAccesser") ;
When Type.GetType을 사용하면 EnterpriseServerBase.dll에 대한 참조를 추가하더라도 Type.GetType("EnterpriseServerBase.DataAccess.IDBAccesser")은 null을 반환합니다. 이는 Type.GetType이 현재 어셈블리에서만 형식 검색을 수행하기 때문입니다. .
2. 리플렉션 중 메서드의 반환 유형이 void인지 확인
Type serviceType = typeof(T);
MethodInfo methodInfo = serviceType.GetMethod(methodName);
판단 methodInfo.ReturnType == typeof(void)가 true일 수 있습니다.