C\#반사 에 대해 알 아야 할 것
형식의 구성원 가 져 오기
Type 류 의 GetMembers 방법 은 이 유형의 모든 구성원 을 가 져 오 는 데 사 용 됩 니 다.방법 과 속성 을 포함 하여 BindingFlags 로 고 를 통 해 이 구성원 들 을 선별 할 수 있 습 니 다.
using System;
using System.Reflection;
using System.Linq;
public class Program
{
public static voidMain()
{
var members = typeof(object).GetMembers(BindingFlags.Public |
BindingFlags.Static | BindingFlags.Instance);
foreach (var member in members)
{
Console.WriteLine($"{member.Name} is a {member.MemberType}");
}
}
}
출력:GetType is a Method
GetHashCode is a Method
ToString is a Method
Equals is a Method
ReferenceEquals is a Method
.ctor is a Constructor
GetMembers 방법 은 BindingFlags 를 전달 하지 않 아 도 되 며,기본적으로 공 개 된 모든 멤버 에 게 돌아 갑 니 다.
대상 을 가 져 오고 호출 하 는 방법
Type 형식의 GetMethod 방법 은 이 유형의 MethodInfo 를 가 져 온 다음 MethodInfo 를 통 해 동적 으로 호출 할 수 있 습 니 다.
비정 상 방법 에 대해 서 는 해당 하 는 인 스 턴 스 를 매개 변수 로 전달 해 야 합 니 다.예제:
class Program
{
public static void Main()
{
var str = "hello";
var method = str.GetType()
.GetMethod("Substring", new[] {typeof(int), typeof(int)});
var result = method.Invoke(str, new object[] {0, 4}); // str.Substring(0, 4)
Console.WriteLine(result); // :hell
}
}
정적 방법 에 대해 대상 매개 변수 가 비어 있 습 니 다.예제:
var method = typeof(Math).GetMethod("Exp");
// Math.Exp(2)
var result = method.Invoke(null, new object[] {2});
Console.WriteLine(result); // (e^2):7.38905609893065
범 형 방법 이 라면 범 형 매개 변 수 를 통 해 범 형 방법 을 만들어 야 합 니 다.예제:
class Program
{
public static void Main()
{
//
MethodInfo method1 = typeof(Sample).GetMethod("GenericMethod");
MethodInfo generic1 = method1.MakeGenericMethod(typeof(string));
generic1.Invoke(sample, null);
//
MethodInfo method2 = typeof(Sample).GetMethod("StaticMethod");
MethodInfo generic2 = method2.MakeGenericMethod(typeof(string));
generic2.Invoke(null, null);
}
}
public class Sample
{
public void GenericMethod<T>()
{
//...
}
public static void StaticMethod<T>()
{
//...
}
}
형식의 인 스 턴 스 를 만 듭 니 다.반사 동 태 를 사용 하여 하나의 유형의 인 스 턴 스 를 만 드 는 데 여러 가지 방식 이 있 습 니 다.가장 간단 한 것 은
new()
조건 으로 성명 하 는 것 이다.new 조건 설명 사용 하기
하나의 방법 에서 인 스 턴 스 를 동적 으로 만들어 야 한다 면 new 조건 설명 을 직접 사용 할 수 있 습 니 다.예 를 들 어:
T GetInstance<T>() where T : new()
{
T instance = newT();
return instance;
}
그러나 이런 방식 은 장면 에 한계 가 있다.예 를 들 어 구조 함수 대 파라미터 의 유형 에 적용 되 지 않 는 다.Activator 클래스 사용 하기
Activator 클래스 동적 으로 클래스 를 만 드 는 것 이 가장 흔 한 방법 입 니 다.예제:
Type type = typeof(BigInteger);
object result = Activator.CreateInstance(type);
Console.WriteLine(result); // :0
result = Activator.CreateInstance(type, 123);
Console.WriteLine(result); // :123
동적 으로 범 형 인 스 턴 스 를 만 들 려 면 먼저 개방 형(예 를 들 어List<>
을 만 든 다음 에 범 형 매개 변수 에 따라 구체 적 인 범 형(예 를 들 어List<string>
으로 전환 해 야 합 니 다.예제:
//
Type openType = typeof(List<>);
//
Type[] tArgs = { typeof(string) };
Type target = openType.MakeGenericType(tArgs);
//
List<string> result = (List<string>)Activator.CreateInstance(target);
만약 당신 이 개방 형 과 구상 형 이 무엇 인지 모른다 면,본문의 마지막 절 을 보십시오.구조 기 반사 사용
또한 반사 구조 기 를 통 해 동적 으로 클래스 를 만 들 수 있 습 니 다.위 에서 Activator 류 를 사용 하 는 것 보다 조금 번 거 롭 지만 성능 이 좋 습 니 다.예시:
ConstructorInfo c = typeof(T).GetConstructor(new[] { typeof(string) });
if (c == null)
throw new InvalidOperationException("...");
T instance = (T)c.Invoke(new object[] { "test" });
FormatterServices 클래스 사용 하기어떤 종류의 인 스 턴 스 를 만 들 려 면 구조 함수 와 속성 초기 화 를 실행 하지 않 고 Formatter Services 의 GetUninitialized Object 방법 을 사용 할 수 있 습 니 다.예시:
class Program
{
static void Main()
{
MyClass instance = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass));
Console.WriteLine(instance.MyProperty1); // :0
Console.WriteLine(instance.MyProperty2); // :0
}
}
public class MyClass
{
public MyClass(int val)
{
MyProperty1 = val < 1 ? 1 : val;
}
public int MyProperty1 { get; }
public int MyProperty2 { get; set; } = 2;
}
속성 이나 방법의 강 한 유형 의뢰 획득반사 로 대상 의 속성 과 방법 을 얻 은 후 강 한 유형의 방법 으로 접근 하거나 호출 하려 면 중간 에 의뢰 를 추가 할 수 있 습 니 다.이러한 장점 은 포장 에 유리 하고 호출 자 는 호출 할 때 어떤 인 자 를 전달 해 야 하 는 지 명확 하 게 알 수 있다 는 것 이다.예 를 들 어 다음 방법 은 Math.Max 방법 을 강력 한 유형의 의뢰 로 추출 합 니 다.
var tArgs = new Type[] { typeof(int), typeof(int) };
var maxMethod = typeof(Math).GetMethod("Max", tArgs);
var strongTypeDelegate = (Func<int, int, int>)Delegate
.CreateDelegate(typeof(Func<int, int, int>), null, maxMethod);
Console.WriteLine("3 5 :{0}", strongTypeDelegate(3, 5)); // :5
이 기술 은 속성 에 도 적용 되 며,강 한 유형의 Getter 와 Setter 를 얻 을 수 있 습 니 다.예시:
var theProperty = typeof(MyClass).GetProperty("MyIntProperty");
// Getter
var theGetter = theProperty.GetGetMethod();
var strongTypeGetter = (Func<MyClass, int>)Delegate
.CreateDelegate(typeof(Func<MyClass, int>), theGetter);
var intVal = strongTypeGetter(target); // :target.MyIntProperty
// Setter
var theSetter = theProperty.GetSetMethod();
var strongTypeSetter = (Action<MyClass, int>)Delegate
.CreateDelegate(typeof(Action<MyClass, int>), theSetter);
strongTypeSetter(target, 5); // :target.MyIntProperty = 5
사용자 정의 기능 반사 가 져 오기다음은 네 가지 흔히 볼 수 있 는 장면 의 예 이다.
예 를 들 어 하나의 클래스 에 사용자 정의 특성(예 를 들 어 MyAtrribute)이 표 시 된 속성 을 찾 습 니 다.
var props = type
.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
.Where(prop =>Attribute.IsDefined(prop, typeof(MyAttribute)));
예시 2,어떤 속성의 모든 사용자 정의 특성 을 찾 아 라.
var attributes = typeof(t).GetProperty("Name").GetCustomAttributes(false);
예제 3.프로그램 집합 에 사용자 정의 특성 이 표 시 된 모든 종 류 를 찾 아 라.
static IEnumerable<Type> GetTypesWithAttribute(Assembly assembly)
{
foreach(Type type inassembly.GetTypes())
{
if (type.GetCustomAttributes(typeof(MyAttribute), true).Length > 0)
{
yield return type;
}
}
}
예제 4,실행 할 때 사용자 정의 기능 의 값 을 읽 습 니 다.
public static class AttributeExtensions
{
public static TValue GetAttribute<TAttribute, TValue>(
this Type type,
string MemberName,
Func<TAttribute, TValue> valueSelector,
bool inherit = false)
where TAttribute : Attribute
{
var att = type.GetMember(MemberName).FirstOrDefault()
.GetCustomAttributes(typeof(TAttribute), inherit)
.FirstOrDefault() as TAttribute;
if (att != null)
{
return valueSelector(att);
}
return default;
}
}
// :
class Program
{
static void Main()
{
// MyClass MyMethod Description
var description = typeof(MyClass)
.GetAttribute("MyMethod", (DescriptionAttribute d) => d.Description);
Console.WriteLine(description); // :Hello
}
}
public class MyClass
{
[Description("Hello")]
public void MyMethod() { }
}
동적 실례 화 인터페이스의 모든 실현 클래스(플러그 인 활성화)반 사 를 통 해 특정한 인터페이스의 모든 실현 류 를 동적 으로 예화 시 키 고 시스템 의 플러그 인 개발 을 실현 하 는 데 자주 사용 된다.예 를 들 어 프로그램 이 시 작 될 때 지정 한 폴 더(예 를 들 어 Plugins)의 dll 파일 을 읽 고 dll 의 모든 인터페이스 클래스 를 반사 적 으로 가 져 오 며 적당 할 때 이 를 예 로 들 수 있 습 니 다.대체로 다음 과 같다.
interface IPlugin
{
string Description { get; }
void DoWork();
}
독립 dll 에 있 는 클래스:
class HelloPlugin : IPlugin
{
public string Description => "A plugin that says Hello";
public void DoWork()
{
Console.WriteLine("Hello");
}
}
시스템 이 시 작 될 때 이 dll 을 동적 으로 불 러 와 IPlugin 인 터 페 이 스 를 실현 하 는 모든 종류의 정 보 를 읽 고 이 를 예 로 들 수 있 습 니 다.
public IEnumerable<IPlugin> InstantiatePlugins(string directory)
{
var assemblyNames = Directory.GetFiles(directory, "*.addin.dll")
.Select(name => new FileInfo(name).FullName).ToArray();
foreach (var fileName assemblyNames)
AppDomain.CurrentDomain.Load(File.ReadAllBytes(fileName));
var assemblies = assemblyNames.Select(System.Reflection.Assembly.LoadFile);
var typesInAssembly = assemblies.SelectMany(asm =>asm.GetTypes());
var pluginTypes = typesInAssembly.Where(type => typeof (IPlugin).IsAssignableFrom(type));
return pluginTypes.Select(Activator.CreateInstance).Cast<IPlugin>();
}
일반적인 인 스 턴 스 의 일반적인 매개 변 수 를 검사 합 니 다.앞에서 구조 범 형 과 구상 범 형 을 언급 했 는데 여기 서 설명 하 자.대부분 우리 가 말 하 는 범 형 은 구조 범 형 을 말 하 는데 가끔 은 구상 범 형 이 라 고도 부른다.예 를 들 어
List<int>
는 하나의 구조 범 형 이다.왜냐하면 그것 은 new 를 통 해 예화 할 수 있 기 때문이다.이에 따라List<>
범 형 은 비구 조 범 형 이 고 때로는 개방 범 형 이 라 고도 불 리 며 실례 화 되 어 서 는 안 된다.개방 범 형 은 반 사 를 통 해 임의의 구상 범 형 으로 전환 할 수 있다 는 점 은 앞에서 예시 가 있다.만약 에 지금 범 형 인 스 턴 스 가 있다 면 특정한 수요 에서 우 리 는 이 범 형 인 스 턴 스 를 구축 하 는 데 어떤 범 형 인 자 를 사용 해 야 하 는 지 알 고 싶 습 니 다.예 를 들 어 누군가가
List<T>
일반적인 인 스 턴 스 를 만 들 고 이 를 매개 변수 로 우리 에 게 전달 하 는 방법 이다.
var myList = newList<int>();
ShowGenericArguments(myList);
우리 의 방법 서명 은 다음 과 같다.
public void ShowGenericArguments(object o)
이때 이 방법의 작성 자로 서 우 리 는 이 o 대상 이 구체 적 으로 어떤 유형의 일반적인 매개 변수 로 구축 되 었 는 지 모른다.반 사 를 통 해 우 리 는 범 형 실례 의 많은 정 보 를 얻 을 수 있다.그 중에서 가장 간단 한 것 은 하나의 유형 이 범 형 인지 아 닌 지 를 판단 하 는 것 이다.
public void ShowGenericArguments(object o)
{
if (o == null) return;
Type t =o.GetType();
if (!t.IsGenericType) return;
...
}
List<>
자체 도 범 형 이기 때문에 위의 판단 이 엄밀 하지 않 기 때문에 우 리 는 대상 이 하나의 구조 범 형List<int>
인지 알 아야 한다.그리고 Type 류 는 유용 한 속성 도 제공 합 니 다.
typeof(List<>).IsGenericType // true
typeof(List<>).IsGenericTypeDefinition // true
typeof(List<>).IsConstructedGenericType// false
typeof(List<int>).IsGenericType // true
typeof(List<int>).IsGenericTypeDefinition // false
typeof(List<int>).IsConstructedGenericType// true
IsConstructedGenericType
와 IsGenericTypeDefinition
는 각각 특정한 범 형 이 구조 범 형 과 비 구조 범 형 인지 판단 하 는 데 사용 된다.Type 의
GetGenericArguments()
방법 을 결합 하면 특정한 범 형 인 스 턴 스 가 어떤 범 형 매개 변수 로 구축 되 었 는 지 쉽게 알 수 있다.예 를 들 어:
static void ShowGenericArguments(object o)
{
if (o == null) return;
Type t = o.GetType();
if (!t.IsConstructedGenericType) return;
foreach (Type genericTypeArgument in t.GetGenericArguments())
Console.WriteLine(genericTypeArgument.Name);
}
이상 은 C\#의 반사 에 대한 상세 한 내용 을 깊이 이해 하고 c\#반사 에 관 한 자 료 는 우리 의 다른 관련 글 을 주목 하 세 요!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
WebView2를 Visual Studio 2017 Express에서 사용할 수 있을 때까지Evergreen .Net Framework SDK 4.8 VisualStudio2017에서 NuGet을 사용하기 때문에 패키지 관리 방법을 packages.config 대신 PackageReference를 사용해야...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.