Powershell 函数限制数据类型

Powershell Function Restrict Data Type

正在尝试创建如下函数:

Function Get-SqlErrorLogPrevious24 {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$True,Position=1)]
        [Microsoft.SqlServer.Management.Smo.Server]$Server
    )

    ($Server.ReadErrorLog()).where{$_.logdate -ge ((Get-Date).AddHours(-24))}
}

不过我注意到,我可以只传递一个字符串而不是服务器对象。

Powershell 中是否有一种方法可以强制执行传入的数据类型,或者它是否始终将字符串隐式转换为 SMO 对象?

没有。 PowerShell 有几个 "strategies" 用于确保您在函数中收到的内容是正确的类型。如果它可以使用其中之一将传递的值(在本例中为字符串)转换为所需的类型(SMO 对象),它将执行此操作。

这是一个great post which lists 10 different strategies.

  1. Direct assignment. If your input is directly assignable, simply cast your input to that type.
  2. Language-based conversion. These language-based conversions are done when the target type is void, Boolean, String, Array, Hashtable, PSReference (i.e.: [ref]), XmlDocument (i.e.: [xml]). Delegate (to support ScriptBlock to Delegate conversions), and Enum.
  3. Parse conversion. If the target type defines a Parse() method that takes that input, use that.
  4. Static Create conversion. If the target type defines a static ::Create() method that takes that input, use that.
  5. Constructor conversion. If the target type defines a constructor that takes your input, use that.
  6. Cast conversion. If the target type defines a implicit or explicit cast operator from the source type, use that. If the source type defines an implicit or explicit cast operator to the target type, use that.
  7. IConvertible conversion. If the source type defines an IConvertible implementation that knows how to convert to the target type, use that.
  8. IDictionary conversion. If the source type is an IDictionary (i.e.: Hashtable), try to create an instance of the destination type using its default constructor, and then use the names and values in the IDictionary to set properties on the source object.
  9. PSObject property conversion. If the source type is a PSObject, try to create an instance of the destination type using its default constructor, and then use the property names and values in the PSObject to set properties on the source object. . If a name maps to a method instead of a property, invoke that method with the value as its argument.
  10. TypeConverter conversion. If there is a registered TypeConverter or PSTypeConverter that can handle the conversion, do that. You can register a TypeConverter through a types.ps1xml file (see: $pshome\Types.ps1xml), or through Update-TypeData.

您可以实现自定义转换属性,如果类型不同会抛出异常:

Add-Type @'
    using System;
    using System.Management.Automation;
    public class EnforceTypeAttribute : ArgumentTransformationAttribute {
        private Type type;
        public EnforceTypeAttribute(Type type) {
            this.type=type;
        }
        public override object Transform(EngineIntrinsics engineIntrinsics, object inputData) {
            if(type.IsInstanceOfType(inputData)) {
                return inputData;
            } else {
                throw new Exception("Incorrect type.");
            }
        }
    }
'@

function f {param([int]$i) $i}
function g {param([EnforceType([int])][int]$i) $i}

f  1  #OK
f '1' #OK
g  1  #OK
g '1' #Error