2009-01-06 48 views
2

我們正在開發一款新的手持軟件。我不能討論應用程序的性質,所以我會用一個例子來代替。模塊化C#Compact Framework 2.0應用程序

我們正在設計管理學校的手持軟件。我們希望模塊化系統的各個方面,以便不同的學校可以使用不同的功能。

我們的系統將從主菜單和登錄屏幕開始。我希望這是系統的基礎,並且將模塊添加到哪裏。即我會有一個名爲SchoolPda的項目。

然後我想擁有不同的模塊。即,我想要一個註冊模塊來處理學生註冊。我想要一個教室模塊來管理教室的清潔等。

我可能會看到這個工作的方式是包括/不包括不同的dll和基本系統的主菜單暴露按鈕來訪問這些模塊,如果dll存在。這就是我們之後的事情。

有沒有人有這樣的經驗嗎?最好的做法是什麼?我們不需要擔心數據庫,因爲數據庫將始終是完整的數據庫,但如果關聯的模塊不存在,方面將不會被填充。

回答

3

我一直在做它兩個方面的項目:

  • 在一個項目中,如果客戶不許可的,我們沒有部署某些DLL文件。這就是你的建議。它運行良好。當然,如果沒有額外的安裝,就沒有辦法啓用這些模塊,但它對於那個應用程序來說非常合理。

  • 在另一個項目中,我們部署了一切,僅向最終用戶展示了客戶獲得許可的菜單,按鈕等。我們這樣做是因爲用戶可以通過爲其添加許可證來輕鬆地添加額外的模塊。當許可證被添加時,這些東西神奇地出現在下次登錄時。

所以根據我的經驗,我會說看看你的授權模式是你決定的一大塊。想想你是否想要即時添加這些額外的模塊。

0

我不知道它是否能在CLR上工作,但看看MEF,創建一種發現和加載你的DLL /模塊的方法。你也可以讓你的模塊有一個GetMenuItem方法(或者類似的方法)來獲取所需的信息,這樣你的主菜單就可以添加一個按鈕。

很顯然,如果有意義的話,可以爲主菜單使用不同的設計,但是您希望它可以真實地模塊化和可擴展,以便您可以編寫核心,並在將來繼續編寫新組件,而不必改變你的核心。

對不起,如果這不會產生最大量的感覺。只是希望給你一個方向的想法。

3

我目前還在開發一個在Compact和Full框架上運行的應用程序,並且是構建模塊化的。

我實現它的方式是它掃描dll的位置並在每個類型上執行並查看它們是否定義了包含有關該類的有用信息的「ScreenInfoAttribute」或「WidgetInfoAttribute」。

這裏有一個片段,它含有3.5的代碼,但是這是因爲我們最近從2.0做了開關,但在2.0

public void Analyze(FileInfo file) { 
     Assembly asm = Assembly.LoadFrom(file.FullName); 
     List<Data.AnyPlugin> types = GetPluginTypes(asm.GetTypes()); 

     if (types.Count > 0) { 
      types.ForEach(x => x.AssemblyPath = file.FullName); 
      if (_plugins.ContainsKey(file.FullName)) { 
       _plugins[file.FullName].Plugins.AddRange(types); 
      } else { 
       AssemblyPlugin asp = new AssemblyPlugin(); 
       asp.Ass = asm; 
       asp.Plugins = types; 
       _plugins.Add(file.FullName, asp); 
      } 
     } 
    } 

    private List<Data.AnyPlugin> GetPluginTypes(Type[] types) { 
     List<Data.AnyPlugin> returnTypes = new List<AnyPlugin>(); 
     foreach (Type t in types) { 
      Data.AnyPlugin st = GetPluginType(t); 
      if (st != null) returnTypes.Add(st); 
     } 
     return returnTypes; 
    } 

    private Data.AnyPlugin GetPluginType(Type type) { 
     if (type.IsSubclassOf(typeof(Screens.bScreen<T>))) { 
      Screens.ScreenInfoAttribute s = GetScreenAttrib(type); 
      if (s != null) { 
       return new Data.ScreenPlugin("", type, s); 
      } 
     } else if (type.IsSubclassOf(typeof(Widgets.bWidget<T>))) { 
      Widgets.WidgetInfoAttribute w = GetWidgetAttrib(type); 
      if (w != null) return new Data.WidgetPlugin("", type, w); 
     } 
     return null; 
    } 

    private Screens.ScreenInfoAttribute GetScreenAttrib(Type t) { 
     Attribute a = Attribute.GetCustomAttribute(t, typeof(Screens.ScreenInfoAttribute)); 
     return (Screens.ScreenInfoAttribute)a; 
    } 
+0

我們做了類似的事情,但Assembly.LoadFrom是一個昂貴的調用。所以我們切換到了一個xml描述符,在這裏我們有所有使用AssemblyName和ClassName定義的插件,這樣您就可以直接調用Activator.CreateInstance。 – 2009-01-06 10:46:20

0

原則作品只是讓每個模塊實現一個共同的接口。添加GetButtons()或GetActions()等方法。

然後,您可以在配置文件中放置有關AssemblyName和ClassName的信息。 現在,它很容易加載指定的程序集並使用Activator.CreateInstance創建類的實例,將其轉換爲接口並調用GetButtons()等方法。

相關問題