我知道Powershell可以调用.NET代码,这可能看起来像这样
PS> [Reflection.Assembly]::LoadFile(($ScriptDir + ".\SharpSvn-x64\SharpSvn.dll"))
PS> $SvnClient = New-Object SharpSvn.SvnClient
我知道在C#有out
个参数的地方,Powershell有[ref]
个参数,可能看起来像这样:
PS> $info = $null
PS> $SvnClient.GetInfo($repo.local, ([ref]$info))
True
PS> $info
(...long output snipped...)
NodeKind : Directory
Revision : 16298
Uri : http://server/path/to/remoterepo
FullPath : C:\path\to\localrepo
(...long output snipped...)
我知道在C#中你可以重载函数,就像SharpSvn库为SvnClient.Update() method做的那样:
Update(ICollection(String))
- 以递归方式将指定路径更新为最新(HEAD)修订版Update(String)
- 递归更新指向最新(HEAD)修订版Update(ICollection(String), SvnUpdateArgs)
- 更新指定版本的指定路径Update(ICollection(String), SvnUpdateResult)
- 以递归方式将指定路径更新为最新(HEAD)修订版Update(String, SvnUpdateArgs)
- 递归更新指定的路径Update(String, SvnUpdateResult)
- 递归更新指向最新(HEAD)修订版Update(ICollection(String), SvnUpdateArgs, SvnUpdateResult)
- 更新指定版本的指定路径Update(String, SvnUpdateArgs, SvnUpdateResult)
- 递归更新指向最新(HEAD)修订版但是,如果我们想将所有这些放在一起怎么办?例如,如果我想调用Update()
的第6个版本,那个带有String和SvnUpdateResult的版本,其中SvnUpdateResult是C#out对象?我的第一直觉是尝试这样的事情:
PS> $repopath = "C:\path\to\localrepo"
PS> $update = $null
PS> $svnclient.update($repopath, [ref]$update)
Multiple ambiguous overloads found for "Update" and the argument count: "2".
At line:1 char:18
+ $svnclient.update <<<< ($repopath, [ref]$update)
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
好的,也许我必须提出论点?
PS> $svnclient.update([string]$repopath, [ref][SharpSvn.SvnUpdateResult]$update)
Multiple ambiguous overloads found for "Update" and the argument count: "2".
At line:1 char:18
+ $svnclient.update <<<< ([string]$repopath, [ref][SharpSvn.SvnUpdateResult]$update)
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
但这似乎也不起作用。我试过的其他事情:
$update
转换为[SharpSvn.SvnUpdateResult][ref]
- 也就是说,颠倒我投出它的顺序。这导致一个错误,指出:“[ref]只能是类型转换序列中的最终类型。”$update
投射到SharpSvn.SvnUpdateResult
:$update = [SharpSvn.SvnUpdateResult]$null
。这导致了我遇到的“多重模糊重载”错误$update
投射到ref
:$update = [ref]$null
。这会导致错误:'无法将“System.Management.Automation.PSReference”类型的“System.Management.Automation.PSReference”值转换为“SharpSvn.SvnUpdateResult”类型。'看起来像两次施法是问题 - 最终施法只是覆盖了第一次施法,他们互不补充。这是发生了什么?有没有办法投两次?还有另一种解决这个问题的方法吗?
提前感谢您的帮助。
答案 0 :(得分:1)
这似乎很难做对。
这是什么版本的PowerShell?
SvnUpdateArgs
和SvnUpdateResult
是否相关(即一个类来自另一个类)?我不会假设。
根据我构建的类似场景,使用PowerShell的当前版本(4.0),我认为这是有效的:
PS> $repopath = "C:\path\to\localrepo"
PS> [SharpSvn.SvnUpdateResult]$update = $null
PS> $svnclient.Update([string]$repopath, [ref]$update)
但是,我只能让它与其中一个重载一起工作!?不确定是不是巧合,但这是我说{{1}时首先列出的重载查看重载定义。
在我的PowerShell版本中,如果我将第二个参数设为$svnclient.Update
,则重载似乎正确解析,该方法运行时没有错误,但是对象分配给&#34; out&#34;参数似乎丢失了。
即使[ref][SharpSvn.SvnUpdateResult]$update
被声明为$repopath
的类型安全,我们仍然需要在传递它时(按值)再次说[string]$repopath = "C:\path\to\localrepo"
。
答案 1 :(得分:1)
当使用类的out参数和具有类似签名的另一个重载调用方法时,PowerShell中似乎存在一个问题(该类可以是此签名中的任何类。)
我为此问题创建了一个简单的repro,为PowerShell创建了filed an issue。
答案 2 :(得分:0)
这可能不是一个理想的解决方案,但您可以使用Add-Type并创建一个包装Update方法的PowerShell友好类型。
Add-Type -TypeDefinition "
public class SvnClientEx
{
public static SvnUpdateResult Update(SvnClient client, string path)
{
SvnUpdateResult result;
client.Update(path, out result);
return result;
}
}
"
$result = [SvnClient]::Update($svnClient, $repopath)
答案 3 :(得分:0)
您可以简单地使用代码块并访问此块中的结果(out)对象:
PS> $repopath = "C:\path\to\localrepo"
PS> $svnclient.update($repopath, {
Write-Host $_.Revision
Write-Host $_.HasRevision
# Access all the Member and Methods of the result object here
})
答案 4 :(得分:0)
你可以做的几件事:
首先,$svnclient.update
返回的结果是PSMethod
。 PSMethod
有Invoke
方法。你可以尝试使用它。
其次,如果这不起作用,你可以使用真实的反思:
# To get all methods:
$svnclient.gettype().getmethods()
# Then filter the results to get overload you need.
# Use GetParameters to get parameters of an overloaded method
# return by GetMethods
# For example (using PS 3.0 features):
$svnclient.gettype().getmethods()|? name -eq Update |
% {write-host "***`n"';$_} | % GetParameters
# Will list parameter sets for each overload of Update, each set separated by stars
# Alternatively use getmethod with appropriate parameters
# GetMethod (link below) can be used to select correct overload without the
# filtering above. The next to the last overload of GetMethod at the link is the one to use
# After obtaining correct overload, then call the Invoke method like this:
$correctOverload.Invoke( $svnclient, @($repopath, [ref] $SvnUpdateResult))