简体   繁体   English

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

[英]How to use Extension methods in Powershell?

I have the following code:我有以下代码:

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;
        }
    }
}

I've loaded the dll in Powershell(Windows 8).我已经在 Powershell(Windows 8)中加载了 dll。 I try to use it the following way:我尝试通过以下方式使用它:

$test = 1.ListPowersOf(2)

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

Instead it says there is no such method.相反,它说没有这样的方法。

I tried the following:我尝试了以下方法:

[BaseDllNamespace]::ListPowersOf(1,2)

Still nothing.依然没有。 I have no namespace in the IntEx class.我在 IntEx 类中没有命名空间。

How do I make it work我如何使它工作

Try this:尝试这个:

[IntEx]::ListPowersOf(1,2)

or或者

[IntEx] | gm -Static -Type Method

to list available static methods.列出可用的静态方法。

You can also use reflection to obtain list of exported types to see if yours is available:您还可以使用反射来获取导出类型的列表,以查看您的类型是否可用:

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

If you really want it to read closer to dot syntax, you could use an implicit or explicit conversion operator on your IntEx type and use it as a POCO instead of as a static extension.如果您真的希望它更接近点语法,您可以在IntEx类型上使用隐式或显式转换运算符,并将其用作 POCO 而不是静态扩展。

It might look something like this...它可能看起来像这样......

$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

I realize this isn't likely to apply to OP at this point, but this question was the first result for my search so I'll post what I figured out here.我意识到这在这一点上不太可能适用于 OP,但这个问题是我搜索的第一个结果,所以我会在这里发布我的想法。

I'm pretty surprised this one isn't already mentioned, but CodeMethods in PowerShell are essentially compiled extension methods for a given type.我很惊讶这个还没有被提及,但是 PowerShell 中的 CodeMethods 本质上是针对给定类型编译的扩展方法。 They're pretty easy to write, too - especially when you already have the extension method.它们也很容易编写 - 特别是当您已经拥有扩展方法时。

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.
    }
}

After loading the type definition into PowerShell:将类型定义加载到 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.

Documentation for code methods is less than ideal. 代码方法的文档不太理想。 If you're building this into a module and defining a CodeMethod in your Types.ps1xml file referenced by your manifest (.psd1), you'll need to include the assembly that defines the code method in the RequiredAssemblies of the manifest.如果要将其构建到模块中并在清单 (.psd1) 引用的 Types.ps1xml 文件中定义 CodeMethod,则RequiredAssemblies在清单的RequiredAssemblies中包含定义代码方法的程序集。 (Including it as RootModule is insufficient because the assemblies of the type(s) must be loaded before the type file(s) are loaded.) (包括它作为RootModule是不够的,因为必须在加载类型文件之前加载类型的程序集。)

Here's how you'd include this type definition in a Types.ps1xml file:以下是在 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM