Установите статическое свойство для статического класса в PowerShell

#powershell

#powershell

Вопрос:

У меня есть класс, в котором есть свойства для класса, но я хочу иметь возможность устанавливать их значения только внутри, но разрешать общедоступный метод доступа к нему. Поскольку в C нет эквивалента PS в классах, подобных этому#:

 public string PropertyName {
   get;
   private set;
}
  

Я рассмотрел реализацию следующего обходного пути в своем классе, чтобы «частные» члены оставались скрытыми с помощью общедоступного средства доступа к свойству:

 class MyClass {
  hidden [string]$_PropertyName
  
  MyClass( $propertyValue ) {
    $this._PropertyName = $PropertyValue
    $this | Add-Member -ScriptProperty -Name 'PropertyName' -Value {
      return $this.$_PropertyName
    } -SecondValue {
      throw "Cannot write value to a readonly property"
    }
  }
}
  

Это хорошо работает и делает то, что я хочу, но у этого класса также есть пара статических свойств, для которых я хочу сделать то же самое из его статического конструктора. Хотя приведенный выше код работает для установки свойства для самого типа класса (заменяющего [MyClass] $this ), существует небольшая особенность, которая делает синтаксис для доступа к свойству «только для чтения» несовместимым с обычным доступом к статическим членам:

 hidden static [string]$_StaticProperty = 'someValue'

static MyClass() {
  [MyClass] | Add-Member -ScriptProperty StaticProperty -Value {
    return [MyClass]::$_StaticProperty
  }
}
  

Я могу получить доступ StaticProperty , но только так, как если бы это был элемент экземпляра:

 [MyClass]::StaticProperty # ==> $null
[MyClass].StaticProperty # ==> someValue
  

Есть ли способ добавить статический элемент к типу, используя Add-Member , чтобы я мог поддерживать согласованный синтаксис средства доступа?

Ответ №1:

Есть ли способ добавить статический элемент к типу с помощью Add-Member, чтобы я мог поддерживать согласованный синтаксис средства доступа?

НЕТ

Add-Member был разработан, чтобы позволить пользователю добавлять синтетические свойства ETS к объектам экземпляра — задолго до того, как кто-либо задумался о добавлении class ключевого слова в грамматику языка.

Другими словами, «статические члены» имеют нулевое значение в контексте ETS, поскольку члены ETS привязаны к идентификатору уже созданных объектов.

Если вы хотите, чтобы поведение члена класса соответствовало C #, используйте C#:

 Add-Type @'
public class MyClass
{
  static MyClass()
  {
    MyClass.StaticProperty = "some value";
  }

  public static string StaticProperty { get; private set; }
}
'@

# Use [MyClass]::StaticProperty
  

Комментарии:

1. Спасибо за ответ. Я пытался использовать классы PowerShell для некоторых вещей вместо PSCustomObjects того, чтобы использовать правильные классы, которые имеют смысл для некоторой работы, которую я выполняю, но обескураживает то, насколько ограничены классы PS, когда другие языки .NET содержат полный набор функций. Начинаю думать, что я должен просто начать писать классы на C #, поскольку классы PS в основном просто хотят определять structs на практике.

2. @BendertheGreatest Не уверен struct , что здесь правильная аналогия (классы PowerShell являются истинными ссылочными типами), но большой вопрос в том, чего вы пытаетесь достичь ? Пример в вашем вопросе довольно общий, но я подозреваю, что вы могли бы заменить переменную, доступную только для чтения в области модуля, для статического свойства в реальной жизни

3. Этот пример скорее пример практики с классами в PowerShell, чтобы уйти от компиляции кода C # с Add-Type помощью производственного кода, посмотреть, что можно и чего нельзя с ними делать. Свойство, доступное только для чтения, работает, если вам нужно задать значение только один раз, но не в том случае, если объект должен измениться позже. Метод работает, но тогда зачем вообще использовать свойства? Это также показывает, что вам нужно сделать, чтобы контролировать, что делает получатель / установщик в целом. Существует интерес к определению поведения getter / setter, поэтому я не думаю, что я не согласен с тем, что PS поддерживает это.