1. 성찰이란 무엇인가:
성찰, 중국어 번역은 성찰이다.
이것은 .Net에서 런타임 유형 정보를 얻는 방법입니다. .Net 애플리케이션은 'Assembly', 'Module', 'Type'이라는 여러 부분으로 구성되며 Reflection은 프로그래머가 관련 정보를 얻을 수 있는 프로그래밍 방법을 제공합니다. 프로그램이 실행되는 동안 이러한 구성 요소에 대해 설명합니다.
리플렉션 개요
리플렉션의 정의: 메타데이터를 검사하고 이에 대한 유형 정보를 수집하는 기능입니다. 메타데이터(컴파일 후 가장 기본적인 데이터 단위)는 어셈블리나 모듈을 컴파일할 때 컴파일러에서 클래스 정의 테이블, 필드 정의 테이블, 메서드 정의 테이블 등을 생성하는 수많은 테이블입니다. System.reflection 네임스페이스에는 이러한 메타데이터 테이블의 코드를 반영(구문 분석)할 수 있는 여러 클래스가 포함되어 있습니다.
2. 리플렉션의 구체적인 용도:
(1) Assembly를 사용하여 어셈블리를 정의 및 로드하고 어셈블리 매니페스트에 나열된 모듈을 로드합니다. 이 어셈블리에서 유형을 입력하고 해당 유형의 인스턴스를 만듭니다.
(2) 모듈을 사용하여 모듈과 모듈에 포함된 클래스를 포함하는 어셈블리를 이해합니다. 또한 모듈에 정의된 모든 전역 메서드 또는 기타 특정 비전역 메서드를 얻을 수도 있습니다.
(3) ConstructorInfo를 사용하여 생성자의 이름, 매개변수, 액세스 한정자(예: pulic 또는 private) 및 구현 세부정보(예: 추상 또는 가상)를 알아보세요. 특정 생성자를 호출하려면 Type의 GetConstructors 또는 GetConstructor 메서드를 사용하세요.
(4) MethodInfo를 사용하여 메서드 이름, 반환 유형, 매개변수, 액세스 한정자(예: pulic 또는 private) 및 구현 세부정보(예: 추상 또는 가상) 등을 이해합니다. 특정 메서드를 호출하려면 Type의 GetMethods 또는 GetMethod 메서드를 사용하세요.
(5) FiedInfo를 사용하여 필드 이름, 액세스 한정자(예: 공개 또는 비공개) 및 구현 세부 정보(예: 정적) 등을 이해하고 필드 값을 가져오거나 설정합니다.
(6) EventInfo를 사용하여 이벤트 이름, 이벤트 핸들러 데이터 유형, 사용자 정의 속성, 선언 유형 및 반사 유형 등을 알아보고 이벤트 핸들러를 추가하거나 제거합니다.
(7) PropertyInfo를 사용하여 속성의 이름, 데이터 유형, 선언 유형, 반사 유형, 읽기 전용 또는 쓰기 가능 상태 등을 이해하고 속성 값을 가져오거나 설정합니다.
(8) ParameterInfo를 사용하여 매개변수의 이름, 데이터 유형, 입력 매개변수인지 출력 매개변수인지, 메소드 시그니처에서 매개변수의 위치 등을 이해합니다.
3. 리플렉션 관련 네임스페이스:
System.Reflection.Assembly
System.Reflection.MemberInfo
System.Reflection
System.Reflection.FieldInfo
System.Reflection.MethodBase
System.Reflection.ConstructorInfo
System.Reflection.MethodInfo
System.Reflection.PropertyInfo
System.Type
4. 반사의 계층적 모델:
참고: 레벨 간에는 일대다 관계가 있습니다.
반영의 역할:
1. 리플렉션을 사용하여 유형의 인스턴스를 동적으로 생성하거나, 기존 객체에 유형을 바인딩하거나, 기존 객체에서 유형을 가져올 수 있습니다
2. 애플리케이션은 리플렉션을 사용하여 특정 작업을 수행할 수 있도록 런타임에 특정 어셈블리에서 특정 유형을 로드해야 합니다.
3. 리플렉션은 주로 클래스 라이브러리와 함께 사용됩니다. 이러한 클래스 라이브러리는 더 많은 기능을 제공하기 위해 유형의 정의를 알아야 합니다.
적용포인트 :
1. 실제 애플리케이션에는 반사 유형을 사용해야 하는 애플리케이션이 거의 없습니다
2. 리플렉션 동적 바인딩을 사용하려면 성능이 저하되어야 합니다
3. 일부 메타데이터 정보는 리플렉션을 통해 얻을 수 없습니다
4. 특정 리플렉션 유형은 CLR용 컴파일러를 개발하는 사람들이 사용하도록 특별히 설계되었으므로 모든 리플렉션 유형이 모든 사람에게 적합한 것은 아닙니다.
6. 성찰의 실제 적용:
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입니다.