리플렉션을 사용하면 코드가 가장 적고 반복을 최소화하면서 C # 3.0 / .NET 3.5로 인터페이스를 구현하는 모든 유형을 어떻게 얻을 수 있습니까?
이것은 다시 작성하고 싶습니다.
foreach (Type t in this.GetType().Assembly.GetTypes())
if (t is IMyInterface)
; //do stuff
답변
내 C # 3.0에서는 이것이 될 것입니다 🙂
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
기본적으로 최소 반복 횟수는 항상 다음과 같습니다.
loop assemblies
loop types
see if implemented.
답변
이것은 나를 위해 일했습니다. 클래스를 반복하고 myInterface에서 파생되었는지 확인합니다.
foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
.Where(mytype => mytype .GetInterfaces().Contains(typeof(myInterface)))) {
//do stuff
}
답변
IFoo 인터페이스를 구현하는 어셈블리에서 모든 유형을 찾으려면
var results = from type in someAssembly.GetTypes()
where typeof(IFoo).IsAssignableFrom(type)
select type;
Ryan Rinaldi의 제안이 잘못되었습니다. 0 유형을 반환합니다. 당신은 쓸 수 없습니다
where type is IFoo
type은 System.Type 인스턴스이고 IFoo 유형이 아니기 때문입니다. 대신 유형에서 IFoo를 할당 할 수 있는지 확인합니다. 예상 결과를 얻을 수 있습니다.
또한 현재 답변으로 표시되어있는 Adam Wright의 제안도 똑같은 이유로 잘못되었습니다. 모든 System.Type 인스턴스가 IFoo 구현자가 아니기 때문에 런타임에 0 유형이 다시 표시됩니다.
답변
이 질문은 매우 오래된 질문이지만, 현재까지의 모든 답변은 어떤 형식을 사용하기 때문에 향후 사용자를위한 또 다른 답변을 추가 할 것이라고 생각했습니다 Assembly.GetTypes
.
GetTypes ()는 실제로 모든 유형을 반환하지만 반드시 유형을 활성화하여 잠재적으로을 던질 수 있음을 의미하지는 않습니다 ReflectionTypeLoadException
.
유형이 돌아 왔을 때 일 것 유형을 활성화 할 수있는하지 않는 전형적인 예이다 derived
에서 base
하지만 base
그와 다른 어셈블리에 정의되어 derived
, 호출 조립하지 않습니다 조립 것을 참조.
우리가 가지고 있다고 가정 해보십시오.
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
ClassC
어느 것이 안에 있다면 AssemblyC
우리는 받아 들여진 대답에 따라 무언가를합니다.
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
그런 다음을 던집니다 ReflectionTypeLoadException
.
이는에 대한 참조없이 AssemblyA
에 AssemblyC
당신이 할 수 없을 것입니다 :
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
다시 말해서 GetTypes에 대한 호출이 확인하고 던지는 ClassB
것은 로드 할 수 없습니다 .
따라서 Phil Haacked 기사 어셈블리 및 Jon Skeet 코드 에서 모든 유형 가져 오기 코드에 따라로드 가능한 유형에 대한 결과 집합을 안전하게 규정 하려면 대신 다음과 같이하십시오.
public static class TypeLoaderExtensions {
public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly) {
if (assembly == null) throw new ArgumentNullException("assembly");
try {
return assembly.GetTypes();
} catch (ReflectionTypeLoadException e) {
return e.Types.Where(t => t != null);
}
}
}
그리고:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}
답변
여기에 다른 답변이 사용 IsAssignableFrom
됩니다. 여기에 설명 된대로 네임 스페이스 FindInterfaces
에서 사용할 수도 있습니다 .System
다음은 현재 실행중인 어셈블리 폴더의 모든 어셈블리를 검사하여 특정 인터페이스를 구현하는 클래스를 찾는 예입니다 (명확성을 위해 LINQ 피하기).
static void Main() {
const string qualifiedInterfaceName = "Interfaces.IMyInterface";
var interfaceFilter = new TypeFilter(InterfaceFilter);
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var di = new DirectoryInfo(path);
foreach (var file in di.GetFiles("*.dll")) {
try {
var nextAssembly = Assembly.ReflectionOnlyLoadFrom(file.FullName);
foreach (var type in nextAssembly.GetTypes()) {
var myInterfaces = type.FindInterfaces(interfaceFilter, qualifiedInterfaceName);
if (myInterfaces.Length > 0) {
// This class implements the interface
}
}
} catch (BadImageFormatException) {
// Not a .net assembly - ignore
}
}
}
public static bool InterfaceFilter(Type typeObj, Object criteriaObj) {
return typeObj.ToString() == criteriaObj.ToString();
}
둘 이상의 인터페이스를 일치 시키려면 인터페이스 목록을 설정할 수 있습니다.
답변
로드 된 모든 어셈블리를 반복하고 모든 유형을 반복하고 인터페이스를 구현하는지 확인하십시오.
같은 :
Type ti = typeof(IYourInterface);
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) {
foreach (Type t in asm.GetTypes()) {
if (ti.IsAssignableFrom(t)) {
// here's your type in t
}
}
}
답변
이것은 나를 위해 일했습니다 (원하는 경우 시스템 유형을 조회에서 제외 할 수 있음).
Type lookupType = typeof (IMenuItem);
IEnumerable<Type> lookupTypes = GetType().Assembly.GetTypes().Where(
t => lookupType.IsAssignableFrom(t) && !t.IsInterface);