Желание статических абстрактных функций в C #.Любая работа вокруг? - PullRequest
0 голосов
/ 24 февраля 2010

Вот моя ситуация. Я работаю с WMI в C #. К счастью, я нашел MgmtClassGen.exe , который сгенерировал все нужные мне классы.

Тем не менее, я проходил автоматически сгенерированные классы и копировал общий код либо в класс Utility, либо в базовый класс. Пока все хорошо, много кода очищено. Но я наткнулся на препятствие. Каждый класс имеет несколько (около 8) статических функций, называемых GetInstances. В основном это две перегрузки, а другая функция просто предоставляет параметры по умолчанию.

Я хотел бы поместить эти функции в базовый класс, потому что они одинаковы для всех классов, кроме 3 переменных. А именно, ClassName (например, "MicrosoftDNS_Zone") объекта, Namespace (например, "root\microsoftdns") объекта и ManagementScope объект.

То, что я сделал в настоящее время, так это; Переместили 2 функции с кодом в базовый класс и добавили 3 параметра для 3 отличий, перечисленных выше. Но для этого все еще требуется 8 функций в каждом классе, которые просто вызывают базовый класс с заполненными параметрами ClassName, Namespace и 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 ) );
        }
    }
}

Ответы [ 3 ]

2 голосов
/ 24 февраля 2010

Почему бы не переместить эти восемь общих функций в отдельный класс в качестве методов экземпляра и инициализировать экземпляр тремя параметрами, которые различаются в зависимости от класса. Затем вы можете агрегировать и предоставлять экземпляр этого вспомогательного класса для каждого из производных типов. Поскольку статические методы не могут использовать какие-либо данные экземпляра, нет причин дублировать их.

Вот пример того, что я имею в виду:

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 голос
/ 24 февраля 2010

Это может быть не вариант для вас, но C # 4.0 поддерживает необязательные аргументы со значениями по умолчанию для методов, что устраняет необходимость в нескольких перегрузках во многих случаях. Например:

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

Вы можете вызвать вышеуказанный метод с помощью ExampleMethod(1) или ExampleMethod(1, 'Test', 9).

0 голосов
/ 24 февраля 2010

Может маленькая фабрика?

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? Могут быть и другие строковые типы, чтобы вы могли его так сильно квалифицировать?
  • пара упоминаний наверху поможет избежать квалифицированных имен
  • понять смысл кода нелегко
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...