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

Iva*_*nov 15 .net c# powershell extension-methods

我有以下代码:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在Powershell中加载了dll(Windows 8).我尝试以下方式使用它:

$test = 1.ListPowersOf(2)
Run Code Online (Sandbox Code Playgroud)

应该返回@(1,2,4,8,16 ...)

相反,它说没有这样的方法.

我尝试了以下方法:

[BaseDllNamespace]::ListPowersOf(1,2)
Run Code Online (Sandbox Code Playgroud)

依然没有.我在IntEx类中没有命名空间.

我如何使其工作

Raf*_*Raf 13

试试这个:

[IntEx]::ListPowersOf(1,2)
Run Code Online (Sandbox Code Playgroud)

要么

[IntEx] | gm -Static -Type Method
Run Code Online (Sandbox Code Playgroud)

列出可用的静态方法.

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

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

  • 尼斯.只是说明一下:虽然PowerShell不允许直接调用扩展方法,但是在定义它的类型的_instance_上,你可以在_type_上将它们称为_static_方法,并将实例作为第一个参数传递. (4认同)

Str*_*iax 10

我意识到这目前不太可能适用于 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.
    }
}
Run Code Online (Sandbox Code Playgroud)

将类型定义加载到 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.
Run Code Online (Sandbox Code Playgroud)

代码方法的文档不太理想。如果您将其构建到模块中并在清单 (.psd1) 引用的 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>
Run Code Online (Sandbox Code Playgroud)