-
Notifications
You must be signed in to change notification settings - Fork 7.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggestion: Duck-typing ValidateProperty attribute #7835
Comments
As an extension of the available |
Perhaps you'd want to apply other validate attributes to properties. [Parameter()]
[Property(
[ValidateRange(0, 10)]
$Count,
[Mandatory = $true, ValidateNotNull()]
$Name
)]
[PSObject]$InputObject |
Now that is a fun idea! Love it! That might have to come enclosed in a script block to avoid needing to create a dozen special cases for the parser, though! |
It will be hard to implement efficiently. Member lookup on PSObject is currently very expensive, including quite a lot of allocations. Could probably be solved if we add new operations of PSObject, that doesn't retreive matching properties, but just confirms their existence. For CLR members, we could cache results based on type, but for PSObjects it's more difficult. I like the idea, though. People concerned about performance have other options. |
We could consider this as proactive vs reactive. You already implemented efficient proactive approch to create a set of similar objects. If users can not use this approach they need reactive approach which is similar to the proposed here. PowerShell engine should be smart enough to turn off the second when using the first. |
I'd suggest using class syntax, much like you'd specify a hypothetical interface that inputs could implement. I use this basic idea in my prototype formatting engine, you can see examples here. Applying the idea here, it might look like: class SourceInfoProxy
{
[string]$SourceFile
[int]$SourceLineNumber
}
function foo
{
param(
[Parameter()]
[ValidateDuckType([SourceInfoProxy])]
[PSObject]$InputObject
)
}
# or maybe the following - which could convert after validation,
# so maybe it's an ArgumentTransformation attribute instead.
function foo
{
param(
[Parameter()]
[ValidateDuckType()]
[SourceInfoProxy]$InputObject
)
} You could go one |
I like that idea, @lzybkr ... but now I have an even better idea than an attribute ... In the second example, as you say, it's an ArgumentTransformation attribute. It's basically a parameter-binding version of injecting a Select-Object and a cast. In the past I've written reshaping filters like this: filter ConvertTo-SourceInfoProxy {
[CmdletBinding()]
param(
[Parameter(ValueFromPipelineByPropertyName)]
[Alias("Line","LineNumber")]
[int]$SourceLineNumber,
[Parameter(ValueFromPipelineByPropertyName)]
[Alias("Path","PSPath", "FullName")]
[string]$SourceFile
)
[SourceInfoProxy]$PSBoundParameters
} What if we could get all of that functionality (including aliases) into the parameter binding itself? The [Alias] property can be applied to properties in classes (although it doesn't currently seem to do anything). I could, therefore trivially generate the filter above, if we had written the class this way: class SourceInfoProxy {
[Alias("Line","LineNumber")]
[string]$SourceLineNumber
[Alias("Path","PSPath", "FullName")]
[int]$SourceFile
} So what we would need is just the ability to either specify a Which brings me to .... What if we had GO style interfaces, instead?In Go, there's no need to say that you Can we do that in PowerShell? What if I could define SourceInfoProxy as an Interface and then just use it as a parameter or variable type and PowerShell automatically validates the properties (and methods?) and even generates property aliases if necessary -- all while leaving the original object intact? This way we wouldn't be throwing away data by coercing the object ... |
So we'd have a |
Well, if we had GO style interfaces, it would just be a parameter of type |
Mmm. That would mean that casting to an interface would have to behave very differently in PS to how it does in C#. Not really sure that's a good idea... |
You're funny @vexx32 -- casting in PowerShell already behaves very differently than how it does in C# and casting to interfaces especially so. PowerShell ignores explicitly defined cast operators in favor of constructors and type coercion already -- and that's not even counting what happens when you cast hashtables... |
@Jaykul Type conversion is very different from C#, but not much of that applies when the target type is an interface, does it? |
To be more specific, PowerShell usually uses the runtime type ( So a "conversion" to an interface is very different than in C#. PowerShell just confirms the object implements the interface, but subsequent uses of the object can access members non-interface members without additional conversions. |
Right -- and my point is ... what if we just changed our definition of "implements the interface" to mean "it looks like a duck, and it quacks like a duck" |
How does c# determine things like this? The Deconstruct method seems to be a salient example - implementing it allows you to treat any object or struct like a deconstuctible tuple-of-sorts which doesn't have to implement any particular interface. |
@vexx32 Since you've started the PR process, I wanted to share a few thoughts on this:
|
|
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you. |
1 similar comment
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you. |
This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes. |
I'd like to propose adding a
ValidateProperties
attribute which would make it easier to validate that an incoming object had specific properties.Hypothetically, use of it might look something like this:
The idea being that this would ensure that the InputObject has a
SourceFile
property of typestring
and aSourceLineNumber
property of typeint
...Or you might even just do:
Which would just validate the properties exist, and not their types.
We might even extend it with a
NotNullOrEmpty
check ...Obviously I can add this in an external module, and I can do this validation with a
ValidateScript
... but it seems like something that's generally useful (along the lines of the[PSTypeName()]
attribute, but with the focus being on the shape of the object, rather than the name.Thoughts?
The text was updated successfully, but these errors were encountered: