Перегрузка по типу в конструкторе Powershell? - PullRequest
3 голосов
/ 26 мая 2020

Мне интересно, можно ли создать класс в Powershell с двумя конструкторами, каждый из которых принимает одно и то же число параметров, но они будут разных типов. Например, я хочу создать что-то вроде следующего:

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, я собираюсь вызвать его либо с помощью пользователя AD из Get-ADUser, в в этом случае я хочу, чтобы первый конструктор запускался, или я собираюсь вызвать его с помощью System.Array, полученного из Import-CSV, и в этом случае я хочу, чтобы запускался второй конструктор.

Я фактически создание их экземпляров в циклах 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

Правильно ли я это делаю?

Ответы [ 2 ]

1 голос
/ 26 мая 2020

Я думаю, что вы, вероятно, получаете ошибку

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))
0 голосов
/ 27 мая 2020

Хорошо, я разобрался. Спасибо всем за вашу помощь.

Чтобы заставить это работать, мне пришлось преобразовать $ 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. файл и может go использовать этот класс для сравнения общих c пользователей.

...