How to use Extension methods in Powershell?

依然范特西╮ 提交于 2021-01-26 03:09:12

问题


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). I try to use it the following way:

$test = 1.ListPowersOf(2)

Should return @(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.

How do I make it work


回答1:


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



回答2:


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.

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



回答3:


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.

I'm pretty surprised this one isn't already mentioned, but CodeMethods in PowerShell are essentially compiled extension methods for a given type. 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:

$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. (Including it as RootModule is insufficient because the assemblies of the type(s) must be loaded before the type file(s) are loaded.)

Here's how you'd include this type definition in a Types.ps1xml file:

<?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>


来源:https://stackoverflow.com/questions/25915450/how-to-use-extension-methods-in-powershell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!