Интерфейс + расширение (смешивающееся) по сравнению с базовым классом

Вам нужно будет создать пустой CimInstance соответствующего типа и использовать метод Add коллекции CimInstanceProperties, чтобы добавить необходимые свойства ключа. Затем используйте метод GetInstance класса CimSession, чтобы получить полный CimInstance со всеми его заполненными данными. Необходимые ключевые свойства задокументированы онлайн для каждого класса, но я сталкивался с ситуациями, когда документация неполная. Чтобы автоматически создаваемая документация не отвлекала вас от того, что вы видите своими глазами, я рекомендую просмотреть свойство __RELPATH для экземпляра класса WMI, на который вы нацелены. Это обеспечит пары ключ-значение.

В PowerShell:

gwmi -Namespace root\virtualization\v2 -Class Msvm_VirtualSystemSnapshotService | select __relpath | fl

, чтобы получить ...

__RELPATH : Msvm_VirtualSystemSnapshotService.CreationClassName="Msvm_VirtualSystemSnapsho
            tService",Name="vssnapsvc",SystemCreationClassName="Msvm_ComputerSystem",Syste
            mName="MYHOSTNAME"

Что означает в C #, вам нужно сделать это:

// Using Microsoft.Management.Infrastructure
private const string _namespace = @"root\virtualization\v2";
private const string _hypervHost = "MYHOSTNAME";

using (var cimSession = CimSession.Create(_hyperVHost))
{
    // Create generic instance with no instance data
    var keyInstance = new CimInstance("Msvm_VirtualSystemSnapshotService");
    // Attach key CimProperties
    keyInstance.CimInstanceProperties.Add(CimProperty.Create("CreationClassName", "Msvm_VirtualSystemSnapshotService", CimFlags.Key));
    keyInstance.CimInstanceProperties.Add(CimProperty.Create("SystemCreationClassName", "Msvm_ComputerSystem", CimFlags.Key));
    keyInstance.CimInstanceProperties.Add(CimProperty.Create("Name", "vssnapsvc", CimFlags.Key));
    keyInstance.CimInstanceProperties.Add(CimProperty.Create("SystemName", _hyperVHost, CimFlags.Key));
    // Retrieve the object
    snapShotService = cimSession.GetInstance(_namespace, keyInstance);
}
29
задан dss539 23 April 2009 в 20:04
поделиться

3 ответа

Недостаток методов расширения: клиенты до C # 3 / VB9 не смогут использовать его так же легко.

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

РЕДАКТИРОВАТЬ: Я только что подумал об еще одном преимуществе, которое может иметь значение . Возможно, что некоторые конкретные реализации могут предоставить более оптимизированные версии некоторых общих методов.

Enumerable.Count является хорошим примером этого - он явно проверяет, реализует ли последовательность IList или не, потому что, если это так, он может вызвать Count в списке, вместо того, чтобы перебирать всю последовательность. Если бы IEnumerable был абстрактным классом с виртуальным методом Count () , он мог бы быть переопределен в List , а не существовать единственная реализация, которая знает о IList в явном виде. Я не говорю, что это всегда актуально, и что IEnumerable должен был быть абстрактным классом (определенно нет!) - просто указываю на это как на небольшой возможный недостаток. Вот где полиморфизм действительно был бы уместен, специализируя существующее поведение (по общему признанию таким способом, который влияет только на производительность вместо результата).

T> был абстрактным классом с виртуальным методом Count () , его можно было бы переопределить в List , а не в единственной реализации, которая знает о IList явно. Я не говорю, что это всегда актуально, и что IEnumerable должен был быть абстрактным классом (определенно нет!) - просто указываю на это как на небольшой возможный недостаток. Вот где полиморфизм действительно был бы уместен, специализируя существующее поведение (по общему признанию таким способом, который влияет только на производительность вместо результата).

T> был абстрактным классом с виртуальным методом Count () , его можно было бы переопределить в List , а не в единственной реализации, которая знает о IList явно. Я не говорю, что это всегда актуально, и что IEnumerable должен был быть абстрактным классом (определенно нет!) - просто указываю на это как на небольшой возможный недостаток. Вот где полиморфизм действительно был бы уместен, специализируя существующее поведение (по общему признанию таким способом, который влияет только на производительность вместо результата).

, а не единственная реализация, которая явно знает о IList . Я не говорю, что это всегда актуально, и что IEnumerable должен был быть абстрактным классом (определенно нет!) - просто указываю на это как на небольшой возможный недостаток. Вот где полиморфизм действительно был бы уместен, специализируя существующее поведение (по общему признанию таким способом, который влияет только на производительность вместо результата).

, а не единственная реализация, которая явно знает о IList . Я не говорю, что это всегда актуально, и что IEnumerable должен был быть абстрактным классом (определенно нет!) - просто указываю на это как на небольшой возможный недостаток. Вот где полиморфизм действительно был бы уместен, специализируя существующее поведение (по общему признанию таким способом, который влияет только на производительность вместо результата).

24
ответ дан 28 November 2019 в 01:39
поделиться

ИМХО, это неправильный вопрос.

Вы должны использовать все для того, для чего он предназначен.

  • Методы расширения не являются членами. Они синтаксически выглядят как члены, поэтому их проще найти.
  • Методы расширения могут использовать только открытый (или внутренний) интерфейс. Многие другие классы могут сделать то же самое. Таким образом, методы расширения не являются реальной инкапсуляцией в обычном порядке.
  • Они являются статическими методами и не могут быть переопределены и не могут быть изменены в модульном тесте. Is - это не языковая особенность, и вызывающая сторона статически связана с ней.

  • Абстрактные базовые классы действительно часто неправильно используют для «повторного использования кода» (вместо реального наследования). Это относится к наследованию в целом.

Вопрос должен звучать так: «Когда я должен использовать интерфейсы, методы расширения или базовые классы?»

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

Редактировать:

Или вопрос должен быть: «Как написать функциональность многократного использования, которая не принадлежит базовому классу?»

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

    Базовые классы являются лишь в редких случаях правильным решением. В сомнении это не так. Вне всякого сомнения, вы должны еще раз подумать об этом.

23
ответ дан 28 November 2019 в 01:39
поделиться

Интерфейсы, как правило, делают код немного чище. Я чувствую, что его немного легче тестировать. Когда вы добавляете расширения, вы добавляете еще большую гибкость, сохраняя чистый тестируемый код.

Для меня абстрактные классы всегда казались неуклюжими, используя интерфейсы, я могу иметь фабрику объектов, которая возвращает объект, специфичный для того, что я пытаюсь выполнить. (разделение интересов).

Просто придумываю У меня есть интерфейс с именем Math, который имеет сложение, вычитание, деление и умножение, а затем у меня есть класс с именем IntMAth, который реализует Math, который оптимизирован для целочисленной математики, и у меня есть другой класс с именем FloatMath, который реализует Math, который оптимизирован для Floating Math, и у меня есть generalMath, который реализует Math, который обрабатывает все остальное.

Когда мне нужно добавить несколько поплавков, я могу вызвать фабрику MathFactory.getMath (typeof (float)), и у него есть некоторая логика, чтобы знать, что если тип I ' Передача m - это float, затем он возвращает класс FloatMath.

Таким образом, все мои классы меньше и удобнее в обслуживании, код, который вызывает классы, меньше и т. д.

1
ответ дан 28 November 2019 в 01:39
поделиться