2017-06-01 45 views
0

我想通過反射一個dll文件來提供我的類運行的小插件機制Plugin(實現我的Plugin-在dll和主要項目之間共享的接口/抱歉命名都相同)提供string類型的activate的屬性和主方法:從dll程序集中獲取方法和屬性

接口:

public interface Plugin 
{ 
    string pluginName{get;set;} 
    void activate(System.Windows.Forms.Form main); 
} 

DLL類:

public class Plugin : WhiteA.Plugin 
     { 
      public string pluginName{get;set;} 

      public void activate(System.Windows.Forms.Form main){ 
       //find the right form to modify it 
       IEnumerable<System.Windows.Forms.ComboBox> ie= GetControlsOfType<System.Windows.Forms.ComboBox>(main); 
       System.Windows.Forms.ComboBox cb=GetControlsOfType<System.Windows.Forms.ComboBox>(main).FirstOrDefault(); 
       cb.Items.Add("Modification"); 
       System.Windows.Forms.MessageBox.Show(cb.SelectedItem.ToString()); 
      } 

      public static IEnumerable<T> GetControlsOfType<T>(System.Windows.Forms.Control root) 
       where T : System.Windows.Forms.Control 
      { 
       var t = root as T; 
       if (t != null) 
        yield return t; 

       var container = root as System.Windows.Forms.ContainerControl; 
       if (container != null) 
        foreach (System.Windows.Forms.Control c in container.Controls) 
         foreach (var i in GetControlsOfType<T>(c)) 
          yield return i; 
      } 
     } 

因此出現這個問題,在程序集中找不到type,名稱爲"Plugin"。試圖從目錄中的所有程序集中獲取所有類型,從它們獲取所有方法/成員/自定義屬性,讓它們登錄等等,但是找不到我的類Plugin,而dll肯定被找到,因爲它不返回MessageBox

string[] files=new string[]{}; 
      string path="Error retrieving path"; 
      try{ 
       path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); 
       files = System.IO.Directory.GetFiles(path, "*.dll"); 
      }catch(Exception exF){ 

      } 
      if(files.Length>0){ 
       foreach (string dll in files){ 
        try{ 
         System.Reflection.Assembly sampleAssembly = System.Reflection.Assembly.LoadFrom(dll); 
         Type myType = sampleAssembly.GetType("Plugin"); 
         System.Reflection.MethodInfo method = myType.GetMethod("activate"); 
         object myInstance = Activator.CreateInstance(myType); 
         method.Invoke(myInstance, new object[]{this}); 
        }catch(Exception exL){ 

        } 
       } 
      }else{ 
       MessageBox.Show("No working plugins detected in " + path.ToString(), "Nothing to activate", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); 
      } 

我知道我的代碼可能看起來非常雜亂大家 - 我想最後try - 塊是唯一與此有關,希望把在類本身和接口一點點的透明度,但 - 而我的英文不是很完美,但我希望有人能幫助我在程序集中找到我的屬性+方法。

編輯

    try{ 
         System.Reflection.Assembly sampleAssembly = System.Reflection.Assembly.LoadFrom(dll); 

         List<Type> list= sampleAssembly.GetTypes().Where(p => 
              p.Namespace == dll && 
              p.Name.Contains("Plugin") 
              ).ToList(); 
         Type myType=list.FirstOrDefault(); 

         //Type myType = sampleAssembly.GetType("Plugin"); 
         System.Reflection.MethodInfo method = myType.GetMethod("activate"); 
         object myInstance = Activator.CreateInstance(myType); 
         method.Invoke(myInstance, new object[]{this}); 

        } 

我就照Getting all types in a namespace via reflection 還是一樣的結果改變它,我做了什麼錯?

+0

我想你需要將命名空間傳遞給'GetType()'?比如'sampleAssembly.GetType(「MyApp.Plugins.Plugin」);'?請注意,您不會傳遞_assembly_名稱 - 請參閱[文檔](https://msdn.microsoft.com/en-us/library/y0cd10tb(v = vs.110).aspx) – stuartd

+0

此處已回答此問題。 https://stackoverflow.com/questions/79693/getting-all-types-in-a-namespace-via-reflection/34869091#34869091 –

+0

@stuartd這意味着我的所有插件都需要有相同的命名空間,對吧?這是必要/允許的嗎? – Kartoffel

回答

0

正如指出的@stuartd

Type myType = sampleAssembly.GetType("WhiteA_Plugin_PausedVideo.Plugin"); 

是解決方案,錯過了命名空間

cb.Items.Add("Modification"); 

不工作,雖然...有什麼建議?

得到它的工作通過控件[「nameOfChild」]直接獲取窗體的子項,幫助按類獲取所有對象的方法在這裏似乎是錯誤的。

插件現在可以工作了,謝謝!