Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Powershell 您能否实现一个动态创建的PSObject,从而使相等和比较有效?_Powershell_Operators_Metaprogramming - Fatal编程技术网

Powershell 您能否实现一个动态创建的PSObject,从而使相等和比较有效?

Powershell 您能否实现一个动态创建的PSObject,从而使相等和比较有效?,powershell,operators,metaprogramming,Powershell,Operators,Metaprogramming,我一直在通过向PSObject动态添加方法来实现临时类型 我希望能够使用“-eq”“-lt”和“-gt”运算符比较我的对象的两个实例(我假设这需要我实现像icomparable和IEquatible这样的接口) 这可能吗?(我的想法可能不是因为这些事情通常发生在类型级别上,我的临时“类型”都是相同的类型) 如果没有,我还能做些什么(除了使用c#)吗?我认为您不能将接口附加到正在创建的psobject上。但是,您可以在实现适当接口并重写适当方法的C#类中创建类型。您甚至可以在here字符串中定义此

我一直在通过向PSObject动态添加方法来实现临时类型

我希望能够使用“-eq”“-lt”和“-gt”运算符比较我的对象的两个实例(我假设这需要我实现像icomparable和IEquatible这样的接口)

这可能吗?(我的想法可能不是因为这些事情通常发生在类型级别上,我的临时“类型”都是相同的类型)


如果没有,我还能做些什么(除了使用c#)吗?

我认为您不能将接口附加到正在创建的psobject上。但是,您可以在实现适当接口并重写适当方法的C#类中创建类型。您甚至可以在here字符串中定义此类型,并使用Add type对其进行编译并将其加载到PowerShell中。然后您只需创建该类型而不是psobject。它应该具有您感兴趣的所有相关属性以及进行比较/相等的能力

根据我的评论,这里是如何在脚本中实现这一点,而执行过程中的麻烦最小,即只要在更改C代码时更改typename变量即可


我认为您无法将接口附加到正在创建的psobject上。但是,您可以在实现适当接口并重写适当方法的C#类中创建类型。您甚至可以在here字符串中定义此类型,并使用Add type对其进行编译并将其加载到PowerShell中。然后您只需创建该类型而不是psobject。它应该具有您感兴趣的所有相关属性以及进行比较/相等的能力

根据我的评论,这里是如何在脚本中实现这一点,而执行过程中的麻烦最小,即只要在更改C代码时更改typename变量即可


正如我在问题中提到的,我正在寻找一种不使用C#和Add Type的方法。我的理由是,我不希望我的整个脚本能够从Powershell中轻松调试,我希望能够在不必重新启动Powershell会话的情况下进行更改。对不起,我肯定错过了关于不使用Add Type的部分。“解决”这个问题的一种方法是参数化类型名,并在C#更改时在执行之间更改它。否则,您可以测试类型是否已经存在,并跳过添加类型调用。我真的不喜欢c#被集成的方式中的不灵活,但这是一个很好的答案。尽管如此,当我在调试脚本的c#部分时不得不不断更改类型名称时,我也很恼火,但当类型名称被参数化时,至少痛苦是显而易见的最小化。:-)正如我在问题中提到的,我正在寻找一种不使用C#和Add Type的方法。我的理由是,我不希望我的整个脚本能够从Powershell中轻松调试,我希望能够在不必重新启动Powershell会话的情况下进行更改。对不起,我肯定错过了关于不使用Add Type的部分。“解决”这个问题的一种方法是参数化类型名,并在C#更改时在执行之间更改它。否则,您可以测试类型是否已经存在,并跳过添加类型调用。我真的不喜欢c#被集成的方式中的不灵活,但这是一个很好的答案。尽管如此,当我在调试脚本的c#部分时不得不不断更改类型名称时,我也很恼火,但当类型名称被参数化时,至少痛苦是显而易见的最小化。:-)
$foo = "Foo"

$src = @"
using System;
public class $foo : IComparable {
    public string Name {get; set;}
    public int Age {get; set;}
    public int CompareTo(object obj)
    {
        $foo other = obj as $foo;
        if (other == null) 
            throw new ArgumentException("arg must be type $foo or not null");
        return Age.CompareTo(other.Age);
    }

    public override bool Equals(object obj)
    {
        if (obj == null) return false;
        if (Object.ReferenceEquals(this, obj)) return true;

        $foo other = obj as $foo;
        if (other == null) 
            throw new ArgumentException("arg must be type $foo or not null");
        return Age.Equals(other.Age) && Name.Equals(other.Name);    
    }

    public override int GetHashCode()
    {
        return Age.GetHashCode() ^ Name.GetHashCode();
    }

    public override string ToString()
    {
        return String.Format("Name: {0}, age: {1}", Name, Age);
    }
}
"@

if (![Type]::GetType($foo))
{
    Add-Type -TypeDefinition $src -Language CSharpVersion3
}

$foo1 = New-Object $foo
$foo1.Age = 47
$foo1.Name = 'Keith'
$foo1


$foo2 = New-Object $foo
$foo2.Age = 45
$foo2.Name = 'John'
$foo2

$foo2 -gt $foo1