2012-05-30 2 views
0

내 제품을 사용하는 개발자가 인터페이스를 구현 한 다음 어셈블리를 실행 폴더에 놓아 제품을 확장 할 수 있도록 허용하려고합니다. 이러한 유형을 찾는 방법은 무엇입니까? 폴더의 모든 단일 DLL을 실행해야합니까? 아니면 원래 응용 프로그램에 포함 된 DLL을 피할 수 있습니까?현재로드되지 않은 어셈블리 목록을 가져올 수 있습니까?

답변

0

결국 나는 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>()); 
    } 
0

새 어셈블리를 다른 폴더 (예 : 호출 또는 플러그인 또는 확장)에 넣은 다음 런타임에 인스턴스를 인스턴스화 할 수 있습니다. 또는 제품 어셈블리 목록을 유지하고 Path.GetFiles를 사용하여 목록에 나타나는 어셈블리를 제거합니다.

+0

없음의 대부분을 제공하는 링크입니다. – leppie

+0

뭐가 좋아? 확장 된 어셈블리를 코어 어셈블리와 분리하지 않으면 모든 것을 더 쉽고 깨끗하게 만들 수 있습니까? – Steve

+0

전에 해본 것처럼 보이지 않습니다. 시도해보십시오. (문제는 메인 앱 폴더와 플러그인 폴더에 '동일한'의존성이 있으므로 2 개의 사본이 작동하지만 좋은 해결책은 아님). – leppie

1

microsoft's solutions을 사용하고 있지 않습니까?
내가 이해하는 한, 당신이 찾고있는 것을 정확히 해결합니다.

+0

MEF 사용에 대해 생각하고 있지만 가장 간단한 구현을 원했고 MEF는 복잡성이 한 단계 높아졌습니다. – Noel

+1

나는 가장 단순한 가능성을 가지고 그것을 사용하는 것이 자신의 의존성 주입 솔루션을 작성하는 것보다 쉽게 ​​추가/유지할 수 있다고 생각하지만, 물론 선택의 여지가있다. – YavgenyP

+0

MEF를 사용하지 않는 또 다른 이유가있다. 구성 요소를 재사용 할 수 있습니다. 개발을 시작했을 때 특정 IoC 컨테이너에 친숙하고 특정 구현에 의존하지 않기를 원했습니다. 지금은 응용 프로그램에서 구성 요소를 사용할 수 있으며 IoC 컨테이너를 사용하면 구성을 사용하여 내 확장을 연결하는 데 사용할 수 있습니다. 그러나 변경하지 않는 항목에 대한 구성이 정말 마음에 들지 않으므로 구현 DLL이 저장소에 덤프 된 경우 확장을 자동으로로드 할 수있는 대안이 필요했습니다. – Noel

0

나는 이것을 사용자 정의 도구에 사용합니다. 내가 도구 디렉토리에 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을 알고 있다면 루프를 통해서만 반복하십시오.

관련 문제