如何在Powershell中使用Extension方法
本文关键字:Extension 方法 Powershell | 更新日期: 2023-09-27 18:22:50
我有以下代码:
using System;
public static class IntEx
{
/// <summary>
/// Yields a power of the given number
/// </summary>
/// <param name="number">The base number</param>
/// <param name="powerOf">the power to be applied on te base number</param>
/// <returns>Powers applied to the base number</returns>
public static IEnumerable<int> ListPowersOf(this int number, int powerOf)
{
for (var i = number; ; i <<= powerOf)
{
yield return i;
}
}
}
我已经在Powershell(Windows 8)中加载了dll。我尝试以以下方式使用它:
$test = 1.ListPowersOf(2)
应返回@(1,2,4,8,16…)
相反,它说没有这样的方法。
我尝试了以下方法:
[BaseDllNamespace]::ListPowersOf(1,2)
还是什么都没有。我在IntEx类中没有命名空间。
如何使其工作
试试这个:
[IntEx]::ListPowersOf(1,2)
或
[IntEx] | gm -Static -Type Method
以列出可用的静态方法。
您也可以使用反射来获得导出类型的列表,看看您的类型是否可用:
[Reflection.Assembly]::LoadFile('C:path'to.dll')|select -ExpandProperty ExportedTypes
我意识到目前这不太可能适用于OP,但这个问题是我搜索的第一个结果,所以我会在这里发布我的发现。
我很惊讶这个还没有提到,但PowerShell中的CodeMethods本质上是为给定类型编译的扩展方法。它们也很容易编写,尤其是当您已经有了扩展方法时。
public static class MyStringExtensions
{
public static string Append(this string source, params char[] characters)
{
foreach (var c in characters)
{
source += c;
}
return source;
}
// named PSAppend instead of Append. This is just a naming convention I like to use,
// but it seems some difference in name is necessary if you're adding the type data
// via a types.ps1xml file instead of through the Update-TypeData command
public static string PSAppend(PSObject source, params char[] characters)
{
if (source.BaseObject is string sourceString)
{
return sourceString.Append(characters);
}
else throw new PSInvalidOperationException();
}
private static string Example() {
var myString = "Some Value.";
Console.WriteLine(myString.Append(" and then some more.".ToCharArray()));
// console output:
// Some Value. and then some more.
}
}
将类型定义加载到PowerShell后:
$method = [MyStringExtensions].GetMethod('PSAppend')
Update-TypeData -TypeName System.String -MemberName Append -MemberType CodeMethod -Value $method
# now you can use the method the same way you'd use an extension method in C#
PS:'> $myString = "Some Value."
PS:'> $myString.Append(" and then some more.")
Some value. and then some more.
代码方法的文档并不理想。如果要将其构建到一个模块中,并在清单(.pd1)引用的Types.ps1xml文件中定义CodeMethod,则需要在清单的RequiredAssemblies
中包含定义代码方法的程序集。(将其包含为RootModule
是不够的,因为必须先加载类型的程序集,然后才能加载类型文件。)
以下是如何在Types.ps1xml文件中包含此类型定义:
<?xml version="1.0" encoding="utf-8" ?>
<Types>
<Type>
<Name>System.String</Name>
<Members>
<CodeMethod>
<Name>Append</Name>
<CodeReference>
<TypeName>MyStringExtensions</TypeName>
<MethodName>PSAppend</MethodName>
</CodeReference>
</CodeMethod>
</Members>
</Type>
</Types>
如果您真的想让它读起来更接近点语法,可以在IntEx
类型上使用隐式或显式转换运算符,并将其用作POCO,而不是静态扩展。
它可能看起来像这样。。。
$code=@'
public class MyExtClass {
public string TheStringValue {get; set;}
public MyExtClass(string theString){
TheStringValue = theString;
}
public int NumberOf(string target)
{
return TheStringValue.Length - TheStringValue.Replace(target, "").Length;
}
public static implicit operator MyExtClass(string value){
return new MyExtClass(value);
}
}
'@
add-type -TypeDefinition $code
$str_eee = "TheTheThe"
$numberOfEs = ([MyExtClass]$str_eee).NumberOf("e")
if(3 -eq $numberOfEs){Write-Host PASS; exit 0}
Write-Host "FAIL";
exit 1