2016-12-21 24 views
11

我試圖實現類似於我想用下圖(問題的結尾)顯示的想法。C#如何「註冊」類「插件」到服務類?

全部編碼從abstract class Base直到DoSomething類。

我的「服務」需要向消費者提供服務已經「註冊」的類型「DoSomethings」的「動作」,在這一點上,我看到我的自己正在重複(複製/粘貼)以下邏輯服務類:

public async Task<Obj1<XXXX>> DoSomething1(....params....) 
     { 
      var action = new DoSomething1(contructParams); 
      return await action.Go(....params....); 
     } 

我想知道是否有無論如何在C#中「註冊」所有「DoSomething的」我要以不同的方式?更有活力,更「複製/粘貼」的東西,同時爲我的消費者階層提供「智能感知」。某種「注入」該服務接受的「DoSomething」的列表。

更新#1 閱讀對策的探討是PanagiotisKanavos談到MEF和檢查的IoC的其他選項後,我沒能找到正是我所期待的。

我的目標是讓我的Service1類(以及所有類似的)表現得像一個DynamicObject但在公認的方法是在自己的構造函數中定義(在這裏我指定究竟哪些DoSomethingX我提供一個方法調用。

: 我有幾個動作(DoSomethingX)爲 「BuyCar」, 「SellCar」, 「ChangeOil」, 「StartEngine」,等等.... 現在,我想創建一個服務 「CarService」 說只應該提供「StartEngine」和「SellCar」的操作,而我可能有其他「服務」與其他「操作」組合。我想要在構造函數中定義這個邏輯每項服務。然後,在消費類,我只是想這樣做:

var myCarService = new CarService(...paramsX...); 
var res1 = myCarService.StartEngine(...paramsY...); 
var res2 = myCarService.SellCar(...paramsZ...); 

而且我想,當我使用「CarService」提供智能感知....

結論:目標是如何在每個服務中「登記」他提供的方法,通過給出「DoSomethingX」列表,並自動將它們作爲「方法」提供......我希望我能夠解釋我的目標/ 希望

換句話說:我只是想能夠說,我Service1類是「提供」行爲DoSomething1, DoSomething2DoSomething3,但與最低線成爲可能。不知怎的,使用類的概念屬性,在那裏我可以做類似這樣的東西:

// THEORETICAL CODE 
[RegisterAction(typeOf(DoSomething1))] 
[RegisterAction(typeOf(DoSomething2))] 
[RegisterAction(typeOf(DoSomething3))] 
public class Service1{ 
    // NO NEED OF EXTRA LINES.... 
} 

enter image description here

+3

你是否檢查過任何現有的插件框架,包括.NET自己的MEF?還是IoC容器?此外,當你有lambda時,你不需要繼承。您可以擺脫整個層次結構,並讓每個插件創建一個包含Do1,Do2'Func >屬性的PluginAction類。 –

+0

@PanagiotisKanavos還沒有,我會看看MEF,謝謝你指出。 – Dryadwoods

+0

http://softwareengineering.stackexchange.com/可能更適合這個問題。參照其他網站時 – nvoigt

回答

2

對於我來說,MEF/MAF是真的東西,你可能會做最後一次在這樣的問題。第一步是制定你的設計。我會做以下幾點:

  1. 實現裝飾設計模式(或您選擇的類似結構模式)。我選擇裝飾器,因爲它看起來像你要通過補充某些具有共享功能的類,這些類沒有在這些類中定義(例如,在你的例子中,組合似乎是首選,而不是繼承)。看到這裏http://www.dofactory.com/net/decorator-design-pattern

  2. 驗證步驟1中POC制定出它是否會做你想做的,如果它被添加作爲一個單獨的DLL(通過使在構建時烘烤不同的csproj IE)。

  3. 評估MEF或MAF是否適合您(取決於您想要去的重量多大)。比較這些與其他技術,如微服務(這將在哲學上改變你目前的做法)。

  4. 實現您選擇的熱插拔(MEF可能是基於您提供的信息的最合理的)。

1

您可以使用反射。 在類服務定義要提供BaseAction類型的列表:

List<Type> providedActions = new List<Type>(); 
providedActions.Add(typeof(DoSomething1)); 
providedActions.Add(typeof(DoSomething2)); 

然後,你可以寫一個選擇在運行時的正確BaseAction一個DoSomething的方法:

public async Task<Obj1<XXXX>> DoSomething(string actionName, ....params....) 
{ 
    Type t = providedActions.Find(x => x.Name == actionName); 

    if (t != null) 
    { 
     var action = (BaseAction)Activator.CreateInstance(t); 

     return await action.Go(....params....); 
    } 
    else 
     return null; 
} 

缺點是客戶不知道服務提供的操作,除非您沒有實施類似的特別方法:

public List<string> ProvidedActions() 
{ 
    List<string> lst = new List<string>(); 
    foreach(Type t in providedActions) 
     lst.Add(t.Name); 
    return lst; 
} 
+0

你可以用'providedActions.Select'(t => t.Name)替代'ProvidedActions()';' – aloisdg

0

也許RealProxy可以幫到你嗎?如果創建ICarService界面,繼承IAction1IAction2,你就可以創建一個代理對象,它將:

  • 找到所有的接口ICarService繼承。
  • 查找這些接口的實現(使用動作工廠或反射)。
  • 創建服務的操作列表。
  • Invoke方法會將調用委託給其中一個操作。

這樣,您將有intellisence只要你想,和動作將建設爲服務塊。某種多繼承的黑客:)

+0

好吧,這再一次依賴於事先知道每個服務將提供什麼,以及@Rhyous在問題評論,「但您希望服務提供它具有的方法,而不是接口」。無論如何,感謝您的意見。 – Dryadwoods

0

在這一點上,我真的很想做到以下幾點:

  • 讓我自己的類屬性RegisterAction(就像我在我的「理論」的例子寫)
  • 擴展Visual Studio Build Process
  • 然後在我的public class LazyProgrammerSolutionTask: Microsoft.Build.Utilities.Task上嘗試查找服務類別並確定RegisterAction屬性。
  • 然後,每一個我都會使用反射我自己的方法注入(我總是複製粘貼的那個方法)......並且從相應的目標「action」類中獲取「簽名」。
  • 最後,再次編譯所有內容。
  • 然後我的「下一個項目」,將消耗這個項目(庫)將有我intellisence,我正在尋找....
  • 有一件事,我真的不知道,它是如何「調試」會這方面的工作....

因爲這也還是一個理論上的(但有可能)的解決方案,我還沒有的源代碼共享。

與此同時,我會留下這個問題的其他可能的方法。