【问题标题】:How to use Extension methods in Powershell?如何在 Powershell 中使用扩展方法?
【发布时间】:2014-09-18 14:28:30
【问题描述】:

我有以下代码:

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 类中没有命名空间。

如何让它发挥作用

【问题讨论】:

  • 看这里,对你有帮助EXTENSION METHODS IN WINDOWS POWERSHELL
  • C# 代码无法编译且无法运行。您在using System 的末尾缺少;,应该有一个using System.Collections.Generic;。并且代码导致无限循环。你可以用yield return (int)Math.Pow(number, powerOf); 替换整个for 循环。

标签: c# .net powershell extension-methods


【解决方案1】:

试试这个:

[IntEx]::ListPowersOf(1,2)

[IntEx] | gm -Static -Type Method

列出可用的静态方法。

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

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

【讨论】:

  • 不错。只是说清楚:虽然 PowerShell 不允许您直接调用扩展方法,但在为其定义的类型的 instance 上,您可以将它们称为 static type 上的方法,并将实例作为第一个参数传递。
【解决方案2】:

我意识到此时这不太可能适用于 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.

Documentation for code methods 不太理想。如果要将其构建到模块中并在清单 (.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>

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-12
      • 1970-01-01
      • 1970-01-01
      • 2010-09-30
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      • 2015-10-20
      相关资源
      最近更新 更多