如何在Powershell中使用扩展方法?

21
我有以下代码:
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类中我没有命名空间。
我该如何使其工作?

4
看这里,可能会对你有帮助 在 Windows PowerShell 中使用扩展方法 - SomeCode.NET
C#代码无法编译也无法运行。在“using System”的末尾缺少一个;,应该加上“using System.Collections.Generic;”。此外,代码会导致无限循环。你可以用“yield return (int)Math.Pow(number, powerOf);”来替换整个“for”循环。 - Keith Hill
3个回答

18

试一下这个:

[IntEx]::ListPowersOf(1,2)
或者
[IntEx] | gm -Static -Type Method

列出可用的静态方法。

您还可以使用反射来获取导出类型列表,以查看您的是否可用:

[Reflection.Assembly]::LoadFile('C:path\to.dll')|select -ExpandProperty ExportedTypes

8
好的。简单来说,尽管PowerShell不能直接调用扩展方法,但对于定义了该方法的类型的实例,您可以将其作为“静态”方法在“类型”上调用,并将实例作为第一个参数传递。 - mklement0

10

我知道这可能不适用于提问者,但这个问题是我搜索的第一个结果,所以我在这里发布我找到的答案。

我很惊讶这个问题还没有被提到,但是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.

代码方法文档 不太理想。如果您正在将此构建到模块中并在您的manifest(.psd1)中引用Types.ps1xml文件来定义CodeMethod,则需要在manifest的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>

2
如果你真的希望它更接近点语法,你可以在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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接