내 제품을 사용하는 개발자가 인터페이스를 구현 한 다음 어셈블리를 실행 폴더에 놓아 제품을 확장 할 수 있도록 허용하려고합니다. 이러한 유형을 찾는 방법은 무엇입니까? 폴더의 모든 단일 DLL을 실행해야합니까? 아니면 원래 응용 프로그램에 포함 된 DLL을 피할 수 있습니까?현재로드되지 않은 어셈블리 목록을 가져올 수 있습니까?
답변
결국 나는 bin에서 찾은 모든 dll을로드하고 검색합니다. 다음은 대부분의 코드입니다. 키 기능은 찾고있는 일반 인터페이스를 찾는 "IsAssignableToGenericType"함수입니다. 나는 믿습니다
이 다른 폴더에 많은 의미를 그들에게 한 추가 솔루션 Implementations of interface through Reflection
static AssemblyLocator()
{
AllDlls = GetAllDlls();
SubscribersInBin = GetSubscribersInBin();
}
public static IEnumerable<Type> TypesImplementingInterface(Assembly[] assemblies, Type desiredType)
{
return assemblies
.SelectMany(assembly => assembly.GetTypes())
.Where(type => IsAssignableToGenericType(type, desiredType));
}
public static bool IsAssignableToGenericType(Type givenType, Type genericType)
{
if (givenType == null) throw new ArgumentNullException("givenType");
if (genericType == null) throw new ArgumentNullException("genericType");
var interfaceTypes = givenType.GetInterfaces();
foreach (var it in interfaceTypes)
{
if (it.IsGenericType)
{
if (it.GetGenericArguments()[0].Name.Equals(genericType.GetGenericArguments()[0].Name))
return true;
}
}
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return (baseType.IsGenericType &&
baseType.GetGenericTypeDefinition() == genericType) ||
IsAssignableToGenericType(baseType, genericType);
}
private static ReadOnlyCollection<string> GetAllDlls()
{
string binFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
IList<string> dllFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList();
return new ReadOnlyCollection<string>(dllFiles);
}
private static ReadOnlyCollection<Type> GetSubscribersInBin()
{
IList<Assembly> assembliesFoundInBin = new List<Assembly>();
foreach (var item in AllDlls)
{
var assembly = System.Reflection.Assembly.LoadFrom(item);
assembliesFoundInBin.Add(assembly);
}
var typesInBin = TypesImplementingInterface(assembliesFoundInBin.ToArray(), typeof(ISubscriber<T>));
return new ReadOnlyCollection<Type>(typesInBin.ToList<Type>());
}
새 어셈블리를 다른 폴더 (예 : 호출 또는 플러그인 또는 확장)에 넣은 다음 런타임에 인스턴스를 인스턴스화 할 수 있습니다. 또는 제품 어셈블리 목록을 유지하고 Path.GetFiles를 사용하여 목록에 나타나는 어셈블리를 제거합니다.
왜 microsoft's solutions을 사용하고 있지 않습니까?
내가 이해하는 한, 당신이 찾고있는 것을 정확히 해결합니다.
MEF 사용에 대해 생각하고 있지만 가장 간단한 구현을 원했고 MEF는 복잡성이 한 단계 높아졌습니다. – Noel
나는 가장 단순한 가능성을 가지고 그것을 사용하는 것이 자신의 의존성 주입 솔루션을 작성하는 것보다 쉽게 추가/유지할 수 있다고 생각하지만, 물론 선택의 여지가있다. – YavgenyP
MEF를 사용하지 않는 또 다른 이유가있다. 구성 요소를 재사용 할 수 있습니다. 개발을 시작했을 때 특정 IoC 컨테이너에 친숙하고 특정 구현에 의존하지 않기를 원했습니다. 지금은 응용 프로그램에서 구성 요소를 사용할 수 있으며 IoC 컨테이너를 사용하면 구성을 사용하여 내 확장을 연결하는 데 사용할 수 있습니다. 그러나 변경하지 않는 항목에 대한 구성이 정말 마음에 들지 않으므로 구현 DLL이 저장소에 덤프 된 경우 확장을 자동으로로드 할 수있는 대안이 필요했습니다. – Noel
나는 이것을 사용자 정의 도구에 사용합니다. 내가 도구 디렉토리에 Directory.GetFiles에 의해 발견 된 모든 DLL을 (또는 EXE 파일)을 통과 루프에서
private static void getImplementedTypes(Type baseType, Assembly assembly, IList<Type> list) {
Type[] types = assembly.GetExportedTypes();
foreach (Type t in types) {
if (baseType.IsInterface) {
Type[] interfaces = t.GetInterfaces();
foreach (Type i in interfaces) {
if (i == baseType) list.Add(t);
}
}
else {
if ((!list.Contains(t)) && (t.IsSubclassOf(baseType)) && (!t.IsAbtract)) {
list.Add(t);
}
}
}
return n;
}
는 :
Assembly assembly = Assembly.LoadFile("toolbox.dll");
List<Type> types = new List<Type>();
getImplementedTypes(typeof(ToolBase), assembly, types);
ToolBase theTool = Activator.CreateInstance(type, true) as ToolBase;
이 인터페이스뿐만 아니라 기본 클래스에 적용됩니다.
구현 된 클래스를 다른 방식으로 찾는 방법을 모르겠습니다. 시간이 좀 걸릴 수 있습니다. 따라서 검색 할 DLL을 알고 있다면 루프를 통해서만 반복하십시오.
- 1. Reflection을 통해 어셈블리 주석을 가져올 수 있습니까?
- 2. 어떻게 휴지통 목록을 가져올 수 있습니까?
- 3. CDI - 이벤트 옵저버 목록을 가져올 수 있습니까?
- 4. Windows에서 프린터 이름 목록을 가져올 수 있습니까?
- 5. Windows 8 알림 목록을 가져올 수 있습니까?
- 6. 브라우저에서 즐겨 찾기 목록을 가져올 수 있습니까?
- 7. Reflector 어셈블리 목록을 배포하십시오.
- 8. 앨범 목록을 가져올 수 없습니다.
- 9. 애플릿을 사용하여 실행중인 프로세스 목록을 가져올 수 있습니까?
- 10. 사용자가 "좋아요"목록을 가져올 수 없음
- 11. java 생성자에서 추상 클래스 목록을 가져올 수 있습니까?
- 12. JS에서 예약어 (변수, 함수, 객체 이름) 목록을 가져올 수 있습니까?
- 13. SVN : 주어진 경로에 대한 개정 번호 목록을 가져올 수 있습니까?
- 14. jQuery에서 요소에 바인딩 된 이벤트 목록을 가져올 수 있습니까?
- 15. imapX를 사용하여 전자 메일 목록을 가져올 수 있습니까?
- 16. 전체 spotify 라이브러리에서 트랙 목록을 가져올 수 있습니까?
- 17. 프로그래밍 방식으로 API를 통해 eBay 범주 목록을 가져올 수 있습니까?
- 18. 원래 PHP에서 클래스에 정의 된 * 메소드 목록을 가져올 수 있습니까?
- 19. Active Directory 속성/속성 목록을 XML 형식으로 가져올 수 있습니까?
- 20. Alfresco에서 노드 유형 (또는 속성 유형) 목록을 가져올 수 있습니까?
- 21. .htaccess 인증 - 파일에서 IP 목록을 가져올 수 있습니까?
- 22. Subversion에서 추가되거나 삭제 된 파일 목록을 가져올 수 있습니까?
- 23. Jquery에서 태그 목록을 가져올 수 없습니다. TAGIT
- 24. Quartz Scheduler에서 작업 목록을 가져올 수 없습니다.
- 25. 실행중인/현재 프로세스 목록을 가져올 수 없습니까?
- 26. 삭제 결과를 가져올 수 있습니까?
- 27. TFS에서 로컬 매핑되지 않은 폴더로 파일을 가져올 수 있습니까?
- 28. 예기치 않은 'targetNamespace'XSD를 가져올 수 없습니다.
- 29. .Net을 사용하면 특정 유형의 모든 "실행중인/활성"인스턴스 목록을 가져올 수 있습니까?
- 30. CSS를 사용하여 정렬되지 않은 목록을 만들 수 있습니까?
없음의 대부분을 제공하는 링크입니다. – leppie
뭐가 좋아? 확장 된 어셈블리를 코어 어셈블리와 분리하지 않으면 모든 것을 더 쉽고 깨끗하게 만들 수 있습니까? – Steve
전에 해본 것처럼 보이지 않습니다. 시도해보십시오. (문제는 메인 앱 폴더와 플러그인 폴더에 '동일한'의존성이 있으므로 2 개의 사본이 작동하지만 좋은 해결책은 아님). – leppie