2013-06-20 60 views
0

我試圖我的應用程序中創建一個基本的插件插件系統,目前我在哪裏建在使用我的WidgetAttribute屬性類的小部件是癥結所在(編譯成EXE)做工精細,但我似乎無法在我寫的任何測試插件中找到任何小部件。無法獲取各類跨組件通過自定義屬性

我用下面的代碼加載組件:

public static void LoadAll() 
    { 
     String[] m_filenames = Directory.GetFiles("plugins", "*.dll", SearchOption.TopDirectoryOnly); 
     foreach (String fn in m_filenames) 
     { 
      Load(Directory.GetCurrentDirectory() + "\\" + fn); 
     } 
    } 

    public static void Load(String filename) 
    { 
     Assembly m_asm = Assembly.Load(File.ReadAllBytes(filename)); 
     PluginAssemblies.Add(m_asm); 
    } 

,然後將下面的代碼來獲取有我的屬性,它表示一個小部件,它的元數據的所有類型:

public static void LoadAllWidgets() 
    { 
     foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) 
     { 
      LoadAllWidgets(assembly); 
     } 

     foreach (Assembly assembly in PluginLoader.PluginAssemblies) 
     { 
      LoadAllWidgets(assembly); 
     } 
    } 

    public static void LoadAllWidgets(Assembly asm) 
    { 
     foreach (Type type in asm.GetTypes()) 
     { 
      WidgetAttribute[] m_attribs = (WidgetAttribute[])type.GetCustomAttributes(false).OfType<WidgetAttribute>().ToArray(); 
      if (m_attribs.Length > 0) 
      { 
       WidgetsByGuid.Add(m_attribs[0].ID, type); 
       WidgetNamesByGuid.Add(m_attribs[0].ID, m_attribs[0].Name); 
       WidgetShowInMenuByGuid.Add(m_attribs[0].ID, m_attribs[0].ShowInMenu); 
      } 
     } 
    } 

當我打電話第二次(即加載來自其他組件的微件)的LoadAllWidgets,我得到的類型陣列內的類型,但隨後GetCustomAttributes返回一個空數組。

屬性定義如下,和相同的源文件在這兩個項目中使用:

using System; 
using System.Reflection; 

namespace WSW.Classes 
{ 
[AttributeUsage(AttributeTargets.Class)] 
public class WidgetAttribute : System.Attribute 
{ 
    public String Name { get; set; } 
    public Guid ID { get; set; } 
    public Boolean ShowInMenu { get; set; } 

    public WidgetAttribute(String guid, String name, Boolean showmenu) 
    { 
     Name = name; 
     ID = Guid.Parse(guid); 
     ShowInMenu = showmenu; 
    } 

    public WidgetAttribute(String guid, String name) 
    { 
     Name = name; 
     ID = Guid.Parse(guid); 
     ShowInMenu = true; 
    } 
} 
} 

誰能告訴我爲什麼我不能讓定製我的組裝之外,從一個類型的屬性,即使我已加載它,並可以看到類型?

EDIT插件類中的其他組件被定義爲如下:

[WSW.Classes.WidgetAttribute("{42544B13-7353-40FD-B1D8-DA46A247110A}", "Testimonials")] 
public partial class Testimonials : UserControl 
{ 
    public Testimonials() 
    { 
     InitializeComponent(); 
    } 
} 

回答

1

在.net的類型的身份是{集名稱+類型名}。

因此,由於您正在使用「兩個項目中都使用了相同的源文件」,這意味着2個不同的程序集(它們恰好具有相同的名稱)中有2個不同的屬性。因此,ether程序集將無法很容易地看到來自其他程序集的屬性(兩者都會看到屬性,只是比較不會按照你想要的方式工作)。

解決方案:

  • 確保每個共享屬性被編譯成只有一個組件和屬性的所有消費者使用該程序集。
  • 比較屬性,而不是類型的名稱。

相同的考慮適用於其他情況下,當使用類型標識。即如果接口作爲源拷貝在2個程序集之間共享,那麼這些接口和實現它們的類將不被認爲是兼容的。

所以往往都共享的共享類型/接口/於程序和相關組件枚舉是地方到共享組裝在一起。這樣的程序集也可以被認爲是公共API,並與設計用於與程序集成的外部組件共享。

請注意,只要您與其他人共享程序集,就意味着您需要版本控制的故事,因爲共享程序集的許多更改(即重命名類型/方法)都會導致相關程序集無法加載或發生故障。

+0

這麼說,創建一個名爲SDK或包含我的接口和屬性,我需要那個名字的東西一個單獨的項目,並使用該SDK作爲參考這兩個主要的應用程序和插件? – bizzehdee

+0

@bizzehdee - 是的。在接口等其他情況下的好處 - 如果使用源代碼副本而不是程序集引用,則會遇到與您在屬性中看到的完全相同的問題。 –

+0

好的,創建了sdk庫,並將它鏈接到雙方作爲參考,現在一切正常,你可以編輯你的答案,讓sdk參考對其他人更爲清晰,並且不能接受。 – bizzehdee

相關問題