【问题标题】:Overload by type in Powershell constructor?Powershell构造函数中的类型重载?
【发布时间】:2020-09-13 12:49:39
【问题描述】:

我想知道是否可以在 Powershell 中创建一个具有两个构造函数的类,它们都接受相同的 number 个参数,但它们的类型不同。例如,我想创建如下内容:

class User {
    [string]$GivenName
    [string]$Surname
    [string]$DisplayName
    [string]$Company
    [string]$PayrollNo
    [string]$Email
    [DateTime]$StartDate
    [DateTime]$LeaveDate

    User([Microsoft.ActiveDirectory.Management.ADAccount]$ADUser) {
        $this.GivenName   = $ADUser.GivenName
        $this.Surname     = $ADUser.Surname
        $this.DisplayName = $ADUser.Name
        $this.PayrollNo   = $ADUser.EmployeeID
        $this.Email       = $ADUser.EmailAddress
    }

    User([System.Array]$TraceUser) {
        $this.GivenName   = $TraceUser.'First Name'
        $this.Surname     = $TraceUser.Surname
        $this.DisplayName = "$($TraceUser.'First Name') $($TraceUser.Surname)"
        $this.Company     = $TraceUser.'Payroll Company'
        $this.PayrollNo   = $TraceUser.'Payroll No'
        $this.Email       = $TraceUser.'E-Mail'
        $this.StartDate   = [datetime]::ParseExact("$($TraceUser.'Start Date') 23:59",'dd/MM/yyyy HH:mm',$null)
        $this.LeaveDate   = [datetime]::ParseExact("$($TraceUser.'Leaving Date') 23:59",'dd/MM/yyyy HH:mm',$null)
    }
}

如果我用 AD 用户作为参数实例化一个对象,它将使用第一个构造函数,但如果我用数组实例化,它将使用第二个构造函数。

这似乎不起作用,我通过在线搜索只能找到如何通过使用不同数量的参数来重载。没有关于基于类型的重载。

这可能吗?

编辑:为了提供更多背景信息,下面的ArcSet 正确猜测了我的错误。我看到了:

Cannot find an overload for "new" and the argument count: "1".

传递给第一个构造函数的 $ADUser 是通过运行 Get-ADUser 获得的。传递给第二个构造函数的 $TraceUser 来自 Import-CSV。

当我实例化 User 类的对象时,我将使用 Get-ADUser 中的 AD User 调用它,在这种情况下,我希望运行第一个构造函数,或者我将调用它来自 Import-CSV 的 System.Array,在这种情况下,我希望运行第二个构造函数。

我实际上是在 ForEach 循环中实例化这些,但我认为这与这里无关。以下是我如何创建这些的示例:

$oneADUser      = Get-ADUser -Filter * -SearchBase $OU
$oneTraceUser   = Import-CSV somefile.csv
$NewADUsers     = @()
$NewTraceUsers  = @()
$NewADUsers    += [User]::new($oneADUser)    # This should use the first constructor
$NewTraceUsers += [User]::new($oneTraceUser) # This should use the second constructor

我这样做对吗?

【问题讨论】:

  • 它应该工作(尽管System.Array 可能不是您使用它的参数类型的最佳选择):) 请提供有关它的更多信息不工作 - 构造函数是否抛出异常?它总是选择一个而不是另一个吗?
  • 因此,经过更多研究,我发现要使其工作,构造函数(以及传递给它们的值)需要强类型。我现在将第二个构造函数更改为 [PSCustomObject]$TraceUser,它现在可以工作了。我没有收到任何错误,但是你瞧,现在它每次都被使用了!即使我将 ADAccount 传递给它,我的 AD 构造函数也从未使用过。

标签: powershell class types constructor overloading


【解决方案1】:

好的,我想通了。感谢大家的帮助。

为了让它工作,我必须先将 $oneTraceUser 转换为 System.Array,然后再将它传递给构造函数。最终的工作代码如下所示:

class User {
    [string]$GivenName
    [string]$Surname
    [string]$DisplayName
    [string]$Company
    [string]$PayrollNo
    [string]$Email
    [DateTime]$StartDate
    [DateTime]$LeaveDate

    User([Microsoft.ActiveDirectory.Management.ADAccount]$ADUser) {
        $this.GivenName   = $ADUser.GivenName
        $this.Surname     = $ADUser.Surname
        $this.DisplayName = $ADUser.Name
        $this.PayrollNo   = $ADUser.EmployeeID
        $this.Email       = $ADUser.EmailAddress
        #$this.LeaveDate  = $ADUser.AccountExpires
    }

    User([System.Array]$TraceUser) {
        $this.GivenName   = $TraceUser.'First Name'
        $this.Surname     = $TraceUser.Surname
        $this.DisplayName = "$($TraceUser.'First Name') $($TraceUser.Surname)"
        $this.Company     = $TraceUser.'Payroll Company'
        $this.PayrollNo   = $TraceUser.'Payroll No'
        $this.Email       = $TraceUser.'E-Mail'
        $this.StartDate   = [datetime]::ParseExact("$($TraceUser.'Start Date') 23:59",'dd/MM/yyyy HH:mm',$null)
        $this.LeaveDate   = [datetime]::ParseExact("$($TraceUser.'Leaving Date') 23:59",'dd/MM/yyyy HH:mm',$null)
    }
}

$NewADUsers = New-Object -TypeName "System.Collections.ArrayList"
$NewTraceUsers = New-Object -TypeName "System.Collections.ArrayList"
$TraceData = Import-CSV $TraceCSV
$ADUsers = Get-ADUser -Filter * -SearchBase $OU -Properties EmployeeID
$TraceUsers = $TraceData | Where-Object 'Payroll Company' -eq $OU.DestinationIndicator
forEach($oneADUser in $ADUsers) {
    $NewADUser = [User]::new($oneADUser)
    forEach($oneTraceUser in $TraceUsers) {
        $NewTraceUser = [User]::new([System.Array]$oneTraceUser)
        $Result = Compare-Users $NewADUser $NewTraceUser
        Write-Output $Result
    }
}

我现在有一个 User 类,根据传递给它的变量类型,它将运行从 AD 或 CSV 文件导入数据的两个类似构造函数之一,并且可以继续使用该类进行比较普通用户之间。

【讨论】:

    【解决方案2】:

    我认为您可能遇到的错误是

    Cannot find an overload for "User" and the argument count: "{Some Number Here like 85}"
    

    那是因为它将您传递的数组视为参数数组

    New-Object User -ArgumentList (Get-ADUser -Filter * | select -First 3)
    

    这将失败并显示消息

    Cannot find an overload for "User" and the argument count: "3"**
    

    如何解决这个问题,在它前面加上 ,

    New-Object User -ArgumentList (,(Get-ADUser -Filter * | select -First 3))
    

    你也可以使用::New()

    [User]::new((Get-ADUser -Filter * | select -First 3))
    

    【讨论】:

    • 感谢您的回复!我在原始帖子中添加了更多细节。我是否应该以某种方式修改我的实例化以允许将字符串数组传递给第二个构造函数?
    猜你喜欢
    • 2021-01-02
    • 2017-11-19
    • 2015-03-30
    • 2015-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多