我希望利用PowerShell 5的新Class
功能创建一个类,我可以在我的项目中使用它来查看数据库的记录,并创建链接和取消链接外键的方法。
下面的类正在使用2个属性,但我需要添加更多但不想复制/粘贴,这就是它目前的工作方式:
# Create a new instance of my Computer class
$computer = [Computer]::new([int]71)
# Change the status of the Server in the DataRow
$computer.Status = "Active"
# Update the Row in the Database
$computer.SaveChanges()
# Link this Server in the Database to a record in the Locations table
$computer.LinkLocation([int]16)
我已经实现了Class
部分甚至一些Methods
,但我想知道我是否可以通过某种方式引用Name
来减少类中所需的代码量ScriptProperty
。
class Computer
{
hidden [System.Data.DataRow]$_dataRow
hidden [System.Data.SqlClient.SqlDataAdapter]$_dataAdapter
hidden GetComputerDetails([int]$serverId)
{
$connectionString = "Server=HomeTestServer\DB01;Database=TestDB;Integrated Security=SSPI;"
$sqlQuery = "SELECT ComputerName, Status FROM tbComputers WHERE Id = $serverId"
$sqlConnection = New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList $connectionString
$sqlCommand = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList $SqlQuery, $sqlConnection
$sqlConnection.Open()
$sqlAdapter = New-Object -TypeName System.Data.SqlClient.SqlDataAdapter -ArgumentList $sqlCommand
$sqlData = New-Object -TypeName System.Data.DataSet
$sqlBuilder = New-Object -TypeName System.Data.SqlClient.SqlCommandBuilder -ArgumentList $sqlAdapter
$sqlAdapter.Fill($sqlData, "Computer")
$this._dataRow = $sqlData.Tables[0].Rows[0]
$this._dataAdapter = $sqlAdapter
}
hidden [object] GetValue([string]$propertyName)
{
return $this._dataRow.$propertyName
}
hidden SetValue([string]$propertyName, $value)
{
$this._dataRow.$propertyName = $value
}
SaveChanges()
{
$this._dataAdapter.Update($this._dataRow)
}
LinkLocation([int]$locationId)
{
$serverId = $this._dataRow.Id
[void](Invoke-Sqlcmd -ServerInstance "HomeTestServer\DB01" -Database TestDB -Query "UPDATE tbComputers SET LocationId = $locationId WHERE Id = $serverId" )
}
Computer([int]$serverId)
{
$this.GetComputerDetails([int]$serverId)
$this | Add-Member -MemberType ScriptProperty -Name ComputerName -Force -Value `
{
# Is there a way to get the ScriptProperty's Name?
$this.GetValue("ComputerName")
} `
{
param
(
$value
)
# Is there a way to get the ScriptProperty's Name?
$this.SetValue("ComputerName", $value)
}
$this | Add-Member -MemberType ScriptProperty -Name Status -Force -Value `
{
# Is there a way to get the ScriptProperty's Name?
$this.GetValue("Status")
} `
{
param
(
$value
)
# Is there a way to get the ScriptProperty's Name?
$this.SetValue("Status", $value)
}
}
}
由于DataRow
直接在DataAdapter
和{{1 }}方法使用ScriptProperty
DataRow
对于我要在Savechanges
中打包的每个媒体资源,我需要制作DataRow
DataAdapter
和Class
,ScriptProperty
有两个属性,看起来不坏但是如果我的SQL表有40个属性怎么办?我真的不想复制和粘贴Getter
行40次。
理想情况下,我正在寻找一种循环方式并动态创建每个Setter
Class
高度简化的例子:
$this | Add-Member...
尝试设置动态属性时收到错误(例如`$ computer.number2 = 17)
ScriptProperty
有没有办法可以根据指定的属性名称动态创建foreach($propertyName in $this._dataRow.Table.Columns)
{
# Looping through doesn't work, my working theory is the Get/Set block don't expand the variable when the Member is being added, only when it's being called
$this | Add-Member -MemberType ScriptProperty -Name $propertyName -Force -Value `
{
# This is the Get block
$this.GetValue($propertyName)
} `
{
param
(
$value
)
# This is the Set block
$this.SetValue($propertyName, $value)
}
}
?
答案 0 :(得分:0)
这可以通过为setter和getter动态生成脚本块来完成。假设使用两种方法定义类Bar
,这两种方法实现了访问字段的一般方法:
class Bar
{
[object] GetFieldValue ( [string] $FieldName )
{
# replace this with code that looks up your value by field name
Write-Host "Invoked GetFieldValue($FieldName)"
return "value of $FieldName"
}
SetFieldValue ( [string] $FieldName, [object] $Value )
{
# replace this with code that sets your field value
Write-Host "Invoked SetFieldValue($FieldName,$Value)"
}
}
然后可以实现一个函数,用动态生成的属性装饰Bar
对象,该属性具有调用这些方法的getter和setter:
function New-Bar
{
param( [string[]]$FieldNames )
# create the new object
$outputObject = [Bar]::new()
# add a property for each field
foreach ( $fieldName in $FieldNames )
{
$getter = [scriptblock]::Create(
"`$this.GetFieldValue('$fieldName')"
)
$setter = [scriptblock]::Create(
"`param(`$p) `$this.SetFieldValue('$fieldName',`$p)"
)
$outputObject |
Add-Member ScriptProperty $fieldName $getter $setter -Force
}
# return the object
$outputObject
}
然后可以像这样访问字段:
$b = New-Bar 'field1','field2'
$b.field1 = 'my value for field 1'
$b.field1
哪个输出:
Invoked GetFieldValue(field1)
value of field1
Invoked SetFieldValue(field1,my value for field 1)