2010-02-24 43 views
0

這是我的情況。我在C#中使用WMI。謝天謝地,我發現MgmtClassGen.exe它生成了我現在需要的所有類。希望在C#中使用靜態抽象函數。任何解決方法?

但是,我一直在瀏覽自動生成的類,並將通用代碼拆分爲Utility類或基類。到目前爲止這麼好,清理了很多代碼。但我碰到了一個障礙。每個類都有幾個(大約8個)被稱爲GetInstances的靜態函數。基本上有2個重載,另一個功能只是提供默認參數。

我想將這些函數放在基類中,因爲它們在所有類中都是相同的,除了3個變量。即,對象的ClassName(如「MicrosoftDNS_Zone」),對象的Namespace(如「root\microsoftdns」)和ManagementScope對象。

我目前所做的是這樣的;將這兩個函數中的代碼移到基類中,並添加了3個參數,用於上面列出的3個差異。但是,這仍然需要在每個班8個功能,只是調用基類與ClassNameNamespace,並填寫Scope參數。

  1. 有什麼辦法來重構這個 代碼,這樣我不需要方法 每個派生類中的「包裝器」?
  2. 我可以只聲明基類中的靜態 方法和 以某種方式得到來自 的派生類的ClassName等嗎?
  3. 反射甚至會在這裏工作嗎?

基類:

namespace WMI 
{ 
    public abstract class Object : System.ComponentModel.Component 
    { 
     // ... 
     protected static WMI.ManagementTypeCollection GetInstances(string className, string namespaceName, ManagementScope statMgmtScope, ManagementScope mgmtScope, EnumerationOptions enumOptions, Func<ManagementObject,WMI.Object> del) 
     { 
      if((mgmtScope == null)) 
      { 
       if((statMgmtScope == null)) 
       { 
        mgmtScope = new System.Management.ManagementScope(); 
        mgmtScope.Path.NamespacePath = namespaceName; 
       } 
       else 
       { 
        mgmtScope = statMgmtScope; 
       } 
      } 
      System.Management.ManagementPath pathObj = new System.Management.ManagementPath(); 
      pathObj.ClassName = className; 
      pathObj.NamespacePath = namespaceName; 
      System.Management.ManagementClass clsObject = new System.Management.ManagementClass(mgmtScope, pathObj, null); 
      if((enumOptions == null)) 
      { 
       enumOptions = new System.Management.EnumerationOptions(); 
       enumOptions.EnsureLocatable = true; 
      } 
      return new WMI.ManagementTypeCollection(clsObject.GetInstances(enumOptions), del); 
     } 

     protected static WMI.ManagementTypeCollection GetInstances(string className, string namespaceName, ManagementScope statMgmtScope, ManagementScope mgmtScope, string condition, String[] selectedProperties, Func<ManagementObject, WMI.Object> del) 
     { 
      if((mgmtScope == null)) 
      { 
       if((statMgmtScope == null)) 
       { 
        mgmtScope = new System.Management.ManagementScope(); 
        mgmtScope.Path.NamespacePath = namespaceName; 
       } 
       else 
       { 
        mgmtScope = statMgmtScope; 
       } 
      } 
      System.Management.ManagementObjectSearcher ObjectSearcher = new System.Management.ManagementObjectSearcher(mgmtScope, new SelectQuery(className, condition, selectedProperties)); 
      System.Management.EnumerationOptions enumOptions = new System.Management.EnumerationOptions(); 
      enumOptions.EnsureLocatable = true; 
      ObjectSearcher.Options = enumOptions; 
      return new WMI.ManagementTypeCollection(ObjectSearcher.Get(), del); 
     } 
    } 
} 

派生類:

namespace WMI.MicrosoftDNS 
{ 
    public class AAAAType : WMI.Object 
    { 
     private static string CreatedWmiNamespace = "root\\microsoftdns"; 
     private static string CreatedClassName = "MicrosoftDNS_AAAAType"; 
     private static System.Management.ManagementScope statMgmtScope = null; 

     // ... 

     public static WMI.ManagementTypeCollection GetInstances() 
     { 
      return GetInstances(null, null, null); 
     } 

     public static WMI.ManagementTypeCollection GetInstances(string condition) 
     { 
      return GetInstances(null, condition, null); 
     } 

     public static WMI.ManagementTypeCollection GetInstances(System.String[] selectedProperties) 
     { 
      return GetInstances(null, null, selectedProperties); 
     } 

     public static WMI.ManagementTypeCollection GetInstances(string condition, System.String[] selectedProperties) 
     { 
      return GetInstances(null, condition, selectedProperties); 
     } 

     public static WMI.ManagementTypeCollection GetInstances(ManagementScope mgmtScope, EnumerationOptions enumOptions) 
     { 
      return WMI.Object.GetInstances(CreatedClassName, CreatedWmiNamespace, statMgmtScope, mgmtScope, enumOptions, mo => new AAAAType(mo)); 
     } 

     public static WMI.ManagementTypeCollection GetInstances(ManagementScope mgmtScope, string condition) 
     { 
      return GetInstances(mgmtScope, condition, null); 
     } 

     public static WMI.ManagementTypeCollection GetInstances(ManagementScope mgmtScope, System.String[] selectedProperties) 
     { 
      return GetInstances(mgmtScope, null, selectedProperties); 
     } 

     public static WMI.ManagementTypeCollection GetInstances(ManagementScope mgmtScope, string condition, System.String[] selectedProperties) 
     { 
      return WMI.Object.GetInstances(CreatedClassName, CreatedWmiNamespace, statMgmtScope, mgmtScope, condition, selectedProperties, mo => new AAAAType(mo)); 
     } 
    } 
} 
+0

對於任何人想知道中,func <的ManagementObject,WMI.Object>是一個黑客用於返回集合項作爲WMI.Object而不是System.Management.ManagementObject用於我的代碼的其餘部分。 – TJMonk15

+0

爲什麼不做collection.Cast ().ToList(); – user76035

+0

由於System.Management.ManagementObjects不是WMI.Objects :-P – TJMonk15

回答

2

爲什麼不將這8個常用函數作爲實例方法移動到一個單獨的類中,並用三個參數根據類進行初始化。然後,您可以聚合並公開每個派生類型的該助手類的實例。由於靜態方法不能使用任何實例數據,因此沒有理由複製它們。

這裏是我的意思的例子:

public class WMIInstance 
{ 
    private readonly string CreatedWmiNamespace = "root\\microsoftdns"; 
    private readonly string CreatedClassName = "MicrosoftDNS_AAAAType"; 
    private readonly System.Management.ManagementScope statMgmtScope = null; 

    public WMIInstance(string namespace, string className, ManagementScope scope) 
    { /*... initialize private members here... */ 

    public WMI.ManagementTypeCollection GetInstances(System.String[] selectedProperties) 
    { return WMI.Object.GetInstances(...); } 

    /* other overloads ... */ 
} 

public class AAAAType : WMI.Object 
{ 
    private static string CreatedWmiNamespace = "root\\microsoftdns"; 
    private static string CreatedClassName = "MicrosoftDNS_AAAAType"; 
    private static System.Management.ManagementScope statMgmtScope = null; 

    private static readonly WMIInstances _instances = new WMIInstance(CreatedWmiNamespace, CreatedClassName, statMgmgtScope); 

    public static WMIInstances Getter { get { return _instances; } } 
} 
+0

解釋...如何讓我的代碼只在基類中? (這是我想要的結果...)? – TJMonk15

+0

我添加了一個例子。基本上,'AAAAType'獲得一個可以訪問'GetInstances()'方法的靜態成員。然後,這些方法反過來變成實用程序類「WMIInstance」的實例方法。這樣你可以爲每個派生的WMI類實例化'WMIInstance',並簡單地用必要的參數初始化它。 – LBushkin

+0

請注意,「WMIInstance」的方法不是靜態的,但「WMIInstance」的創建實例是「AAAAType」的靜態成員。 – LBushkin

1

它可能不是一個選擇,但C#4.0支持optional arguments與方法的默認值,它不需要在很多情況下有多重過載。例如:

public void ExampleMethod(int required, string optionalstr = "default string", int optionalint = 10)

你可以打電話與ExampleMethod(1)ExampleMethod(1, 'Test', 9)上述方法。

+0

是的,我正在使用C#4.0,並計劃執行此操作。但是,這看起來讓我需要在接近75個文件中複製/操作2個函數(實際上有2個不同的超載)。此外,如果我需要與任何其他WMI類一起工作......並且我總是討厭在任何地方重複代碼,尤其是在75個以上的文件中: - \ – TJMonk15

+0

也許您可以使用自定義屬性和反射來設置和讀取每個類的唯一值? http://msdn.microsoft.com/en-us/library/z0w1kczw%28VS.100%29.aspx – tbreffni

+0

這將在基類的靜態上下文中正常工作嗎? – TJMonk15

0

也許一個小工廠?

class Config { string ClassName; string Namespace; ManagementScope Scope; } 

static class Factory { 
    public static readonly Dictionary<Type, Config> Configs = new ...; 

    static GetInstances(Type requestedType, ...) { 
     var config = Configs[requestedType]; 
     // work with it... 
    } 
} 

class AAAAType { 
    static AAAAType{ 
      Factory.Configs.Add(typeof(AAAAType), new Config{ ... }); 
    } 
} 

它可能不是完美的代碼,但我不想離開最初的建議。此外,我真的不喜歡它,並會推薦你的想法重新設計,因爲:

  • 干擾太大
  • 6個參數的方法,包括函數指針真的嗎?
  • System.String?可能還有其他字符串類型,這樣你就可以認定它很強大?
  • 一對夫婦在頂部usings將有助於避免限定名
  • 獲得代碼的意圖是不容易的
+0

這主要是從微軟工具自動生成的代碼〜滾動眼睛〜是的,它沒有多大意義。我試圖清理它,因此這個問題。 :) – TJMonk15