希望C#中的静态抽象函数。有什么工作吗?

时间:2010-02-24 18:40:50

标签: c# oop

这是我的情况。我正在使用C#中的WMI。值得庆幸的是,我发现MgmtClassGen.exe生成了我现在需要的所有类。

但是,我一直在浏览自动生成的类,并将公共代码转换为Utility类或基类。到目前为止一切都那么好,清理了很多代码。但我遇到了麻烦。每个类都有几个(大约8个)静态函数,称为GetInstances。基本上有2个重载,而另一个函数只是提供默认参数。

我想将这些函数放在基类中,因为它们在所有类中是相同的,除了3个变量。即,对象的ClassName(如“MicrosoftDNS_Zone”),对象的Namespace(如“root\microsoftdns”)和ManagementScope对象

我目前所做的是这个;将包含其中代码的2个函数移动到基类,并为上面列出的3个差异添加了3个参数。但是这仍然需要在每个类中使用8个函数来调用基类,并填充ClassNameNamespaceScope个参数。

  1. 有没有办法重构这个 代码,以便我不需要该方法 每个派生类中的“包装器”?
  2. 我可以直接声明静态 基类中的方法和 以某种方式从中获取ClassName等 派生类?
  3. 反思会不会在这里发挥作用?
  4. 基类:

    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 ) );
            }
        }
    }
    

3 个答案:

答案 0 :(得分:2)

为什么不将这八个常用函数作为实例方法移动到单独的类中,并使用因类而异的三个参数初始化实例。然后,您可以在每个派生类型上聚合并公开该帮助程序类的实例。由于静态方法不能使用任何实例数据,因此没有理由复制它们。

这是我的意思的一个例子:

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; } }
}

答案 1 :(得分:1)

它可能不是您的选择,但C#4.0支持optional arguments方法的默认值,这消除了在很多情况下需要多次重载的需要。例如:

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

您可以使用ExampleMethod(1)ExampleMethod(1, 'Test', 9)调用上述方法。

答案 2 :(得分: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?可能有其他字符串类型,以便您认定它强大吗?
  • 顶部的几个使用将有助于避免合格的名称
  • 获取代码的意图并不容易