-
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
The PSObject implementation does not handle classes derived from DynamicObject properly #6567
Comments
This is not specific to
It looks like we aren't handling
|
The original title was a bit confusing given that PowerShell, from V3 on, uses the DLR extensively. I've updated it to more accurately reflect what I think the problem is. @jazzdelightsme - are you ok with the updated title? |
Sure. Thank you! |
Looking at the DLR stuff is ... intimidating. It's hard to tell where to grab on first. Any hints? |
I believe this is the code that is supposed to cover your scenario. It was likely tested (I don't typically write code like that without testing) so I'm not sure why it doesn't work - but I'd start there. |
Thanks @lzybkr! I believe that code does in fact work. That's why things like But for When using wildcards (like However, the For the non-wildcard case (like If dynamic members were to be exposed to If that's not the right approach... then what will |
Ah, of course. That's the problem then. The The I believe the right fix is to use a dynamic site in the same way that PowerShell does for the This problem affects It would seem this scenario is a corner case - it has never worked and this is the first report I've seen. That said, fixing it has a nice benefit - performance should improve even when not using dynamic objects. A fix does need to be careful though - some of those commands accept wildcards for property names. It might be best to keep the existing code for any use of wildcards. |
Okay, it may be beyond my ken, but I'll buy you lunch, @lzybkr, if you are willing to talk me through what you think the "right" change would look like... |
No need to buy me lunch, but I'm happy to chat. To get you started - you can find similar code here. The difference is - you'll use |
This change allows dynamic (DLR) objects to work better with Select-Object. Dynamic (DLR) objects work in some places, but not others. MshExpression is a place where they previously didn't work, and this change fixes that (see the linked issue for the simple repro and explanation: fixes PowerShell#6567) This change addresses both wildcard and non-wildcard cases. In the non-wildcard case, if the target base object is an IDMOP, we just attempt a dynamic bind--if it fails, you'll get the same error that you would have before ("The property 'Blarg' cannot be found"). In the wildcard case, we already call the IDMOP's `GetDynamicMemberNames` function and match the returned names--this change just allows us to use those results. However, this change *only* affects things that use `MshExpression`, like `Select-Object`. Other cmdlets, such as `Where-Object`, do not use `MshExpression`, and so have similar problems. Changing every cmdlet that accesses `.Members[_propName]` in a way similar to what has been done for `MshExpression` in this commit would be painful, would be easy to miss in new commands, and wouldn't help external code that accesses via `.Members`, so I think a better solution might be to expose the dynamic members as part of the `.Members` collection directly.
I came up with an PoC (see here) that seems to work well, but it only addresses Next I'll try pushing the solution down a bit further, into the |
This change allows dynamic (DLR) objects to work better with Select-Object. Dynamic (DLR) objects work in some places, but not others. MshExpression is a place where they previously didn't work, and this change fixes that (see the linked issue for the simple repro and explanation: fixes PowerShell#6567) This change addresses both wildcard and non-wildcard cases. In the non-wildcard case, if the target base object is an IDMOP, we just attempt a dynamic bind--if it fails, you'll get the same error that you would have before ("The property 'Blarg' cannot be found"). In the wildcard case, we already call the IDMOP's `GetDynamicMemberNames` function and match the returned names--this change just allows us to use those results. However, this change *only* affects things that use `MshExpression`, like `Select-Object`. Other cmdlets, such as `Where-Object`, do not use `MshExpression`, and so have similar problems. Changing every cmdlet that accesses `.Members[_propName]` in a way similar to what has been done for `MshExpression` in this commit would be painful, would be easy to miss in new commands, and wouldn't help external code that accesses via `.Members`, so I think a better solution might be to expose the dynamic members as part of the `.Members` collection directly.
Dynamic (DLR) objects work in some places today, but not others. This change expands that support to ForEach-Object, Where-Object and the family of cmdlets that use MshExpression (Select-Object, etc.). (see the linked issue for the simple repro and explanation: fixes PowerShell#6567) This change addresses both wildcard and non-wildcard cases. In wildcard cases, it uses the existing support of generating PSDynamicMember objects for names returned by GetDynamicMemberNames. In non-wildcard cases, a dynamic property access is attempted whether or not the name shows up in GetDynamicMemberNames, but a truly "blind" access is only attempted if we see that the base object is an IDMOP. If the dynamic access fails, you'll get the same or a similar error experience as before ("The property 'Blarg' cannot be found", or no error at all, depending on the cmdlet and the strict mode setting). The included test coverage includes a stub for the .ForEach operator--once people are happy with this change, I can continue by adding support there. This change should allegedly also have positive perf impact, though in actual perf testing, although it does seem ever-so-slightly faster, I found it difficult to measure much difference at all.
This repro’s on 5.1 and 6. The problem is that if I have a DynamicObject that has a dynamic property “Foo”, things like
$obj.Foo
work, butSelect-Object -ExpandProperty Foo
do not.Steps to reproduce
Expected behavior
Actual behavior
Environment data
The text was updated successfully, but these errors were encountered: