2012-01-04 4 views
0

클래스를 변수로 가져 와서 함수를 호출하고 속성을 가져올 수 있습니까?
나는 반성을 들여다 보라고 들었지만 DLL을 컴파일 할 때 DLL이 알려지지 않았을 때 어떻게 처리되는지 알지 못합니다.로드 된 DLL에서 클래스를 관리하는 방법은 무엇입니까?

명확해야 함 : DLL을로드하는 '기본'클래스가 있으며 DLL 내에 클래스 인스턴스를 만들고 속성을 직접 가져 오려고합니다.

+0

게시물입니다 ..? 리플렉션은 어셈블리에서 얻는 방법입니다. 메소드, 이름, 유형 요법 .. 리플렉션을 읽습니다. LateBinding이 수행되는 방식에 대한 이해를 얻으면 리플렉션을 매우 간단하게 처리합니다. 관리되는 환경과 비교되지 않습니다. 레거시 코드 일에 관리되지 않습니다. – MethodMan

+0

무엇을 알고 있습니까? 호출해야하는 DLL의 메소드? (당신이 관리되지 않는 것을 사용하고있는 것 같습니다) – Adrian

+0

관리되는 DLL입니까, 관리되지 않는 DLL입니까? – Krizz

답변

4

당신은 같은 것을 수행해야합니다

Assembly asm = Assembly.Load("DLL File Path"); //load DLL from file 
Type t = asm.GetType("Test.ExternalDllTest"); //fully qualified name 
dynamic oDynamic = Activator.CreateInstance(t, args);//create an instance of specified type, and assign it to DYNAMIC object 

편집 DLL가 가지고있는이 이 DLL을 관리 할 수 ​​당연히

oDynamic.SomeMethod(); //call the method of your type. Being DYNAMIC it will route the call to correct method. 

(그래서 .NET 언어로 작성)

나는 이것을 컴파일하지 않았다. 솔직히 말해서, 기본적으로 이것은 어떻게하는지에 대한 아이디어입니다.

여기에 또한 example이 도움이 될 수 있습니다. 경우 다른 .NET dll을 얘기

+0

나는 이걸 멀리 가지고 있지만 여기서 어떻게 할 수 있니? 'o'로 무엇을 할 수 있습니까? – John

+0

@ 존 : 내 편집 된 게시물을 참조하십시오. 이미 알고있는 유형으로 캐스트하면됩니다. 그건. – Tigran

+0

'namespace.classname'이 @ compile time을 모르는 경우 어떻게 할 수 있습니까? VS에서 '유형 또는 네임 스페이스 이름'네임 스페이스 '를 찾을 수 없습니다'라는 PS를 관리합니다. – John

2

당신은 거기에있는 모든 종류의 어셈블리를로드 얻기 위해 이것을 사용할 수 있습니다 :

:

var asm = Assembly.LoadFile("yourassembly.dll"); 
foreach (var t in asm.GetTypes()) 
{ 
     Console.WriteLine("Type: {0}", t.Name); 
} 

당신은 Activator 중 하나를 사용하여 객체를 인스턴스화 할 수 있습니다

Activator.CreateInstance(t, additional arguments); 

하거나 GetConstructors에 해당 유형의 모든 public 생성자의 목록을 얻을 수 있습니다 :

var constructors = t.GetConstructors(); 

그러나 당신이 찾고있는 유형과 그것의 생성자 매개 변수가 무엇인지 알지 못한다면 그것을 instatiate하고 사용하려고 시도하는 것이 약간 무의미합니다.

0

로드 된 DLL 및로드 프로그램을 통해 액세스 할 수있는 인터페이스 (IKnowAboutSomething)를 작성하십시오.

로드 된 DLL을 검색하여이 인터페이스를 구현하는 클래스를 찾으십시오.

그런 다음 당신은 (당신이 인터페이스를 알고있다) 당신이 볼 수있는 유형의 인스턴스 이제 당신은 단지 등 귀하의 IKnowAboutSomething.GetThingINeed() 메소드를 호출하면 사물과 상호 작용할 수

을 만들 Activator.CreateInstance로 사용할 수 있습니다 당신은 컴파일 시간에 대해 모른다. (글쎄, 그들은 인터페이스를 사용하고 있기 때문에 약간의 협약을 맺었습니다.)

이 코드를 두 프로젝트에서 액세스 할 수있는 외부 DLL (예 : Core.Dll)에 넣으십시오.

using System.IO; 
public interface ISettings 
{ 
    /// <summary> 
    /// Will be called after you Setup has executed if it returns True for a save to be performed. You are given a Stream to write your data to. 
    /// </summary> 
    /// <param name="s"></param> 
    /// <remarks></remarks> 
    void Save(Stream s); 
    /// <summary> 
    /// Will be called before your Setup Method is to enable the loading of existing settings. If there is no previous configuration this method will NOT be called 
    /// </summary> 
    /// <param name="s"></param> 
    /// <remarks></remarks> 

    void Load(Stream s); 

    /// <summary> 
    /// Your plugin must setup a GUID that is unique for your project. The Main Program will check this and if it is duplicated your DLL will not load 
    /// </summary> 
    /// <value></value> 
    /// <returns></returns> 
    /// <remarks></remarks> 

    Guid Identifier { get; } 
    /// <summary> 
    /// This Description will be displayed for the user to select your Plugin. You should make this descriptive so the correct one is selected in the event they have multiple plugins active. 
    /// </summary> 
    /// <value></value> 
    /// <returns></returns> 
    /// <remarks></remarks> 

    string Description { get; } 

} 

이제 기본 프로젝트에서 위 DLL에 대한 참조를 추가하십시오.

주 프로젝트에서로드 할 계획 인 디렉터리 (c : \ myDlls * .dll)를 검색하려면 DirectoryInfo 등을 사용하십시오.

DLL을 찾았 으면 어셈블리 asm = Assembly.LoadFrom (filename)을 사용하여로드하십시오.

이제 주 프로젝트에서이 작업을 수행 할 수 있습니다.

foreach (Type t in asm.GetTypes()) 
{ 
    if (typeof(ISettings).IsAssignableFrom(t)) 
    { 
     //Found a Class that is usable 
     ISettings loadedSetting = Activator.CreateInstance(t); 
     Console.WriteLine(loadedSetting.Description); 
    } 
} 
+0

제발 이걸 구현하는 방법에 대한 예를 들어 주시겠습니까? 하나는 로더 용이고 다른 하나는 외부 DLL 용입니다. – John

+0

@ 존 편집을 참조하십시오 –

+0

이것은 일하는 좋은 방법입니다, 고마워요. 'guid'란 무엇입니까? 그 기능은 무엇입니까? – John

0

예. 다음 코드는 'DLL'과 'EXE'를 일치하는 파일에 대한 디렉토리 트리를 통해 검색 내가 플러그인 디렉토리 트리를 검색하고 WPF ValueConverter 클래스의 목록을 반환 사용하는 방법 ...

private static List<IValueConverter> GetValueConverters(string rootDirectoryName) 
{ 
    List<IValueConverter> result = new List<IValueConverter>(); 
    string[] exts = new string[]{"*.exe", "*.dll"}; 
    DirectoryInfo di = new DirectoryInfo(rootDirectoryName); 
    foreach(string ext in exts) 
    { 
     foreach(FileInfo fi in (di.GetFiles(ext, SearchOption.AllDirectories))) 
     { 
      Assembly a = Assembly.LoadFrom(fi.FullName); 
      try 
      { 
       List<Type> ts = a.GetExportedTypes().ToList(); 
       foreach (Type t in ts) 
       { 
        var d2 = t.GetInterfaces().Where(q => q.Name == "IValueConverter"); 
        if (d2.Count() > 0) 
        { 
         result.Add(Activator.CreateInstance(t) as IValueConverter); 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
      } 
     } 
    } 
    return result; 
} 

입니다. 하나를 찾으면로드하고 WPF ValueConverters가 있는지 확인합니다.

코드를 찾으면 인스턴스가 만들어져 목록에 추가되고 궁극적으로 목록이 반환됩니다. 물론 'dll'과 'exe 's'는 관리되는 세계에 있어야합니다. ValueConverters가 아닌 다른 클래스에 관심이 있다면 적절하게 변경해야합니다.

이 목적 구축 방법 (즉, 내가 결과에 무슨 일이 일어날 알고)과 코드가 당신이 가지고있는 코드 ... 단지 예로서 여기에 주어진

관련 문제