View Single Post
Old 04-04-2007   #4 (permalink)
Doug


 
 

Re: -is [System.Management.Automation.PSCustomObject]

Thanks for digging. Great info.

"Ryan Milligan" wrote:

> Huh...this is interesting. If you open up System.Management.Automation.dll
> and take a look at the code for PSObject's constructor, you'll see the
> problem. If you construct an empty PSObject without passing an object, it
> calls CommonInitialization() with a default PSCustomObject (retrieved from a
> static field on PSCustomObject), which checks the object that's passed in to
> see if it's a PSCustomObject and, if so, sets immediateBaseObjectIsEmpty to
> true. The end result is that PSObjects that wrap around PSCustomObjects
> actually think they don't have an object at all, which is probably the point
> of PSCustomObject. They exist entirely to act as containers for dynamic
> properties.
>
> Now we get to the interesting part. There are two ways to retrieve the base
> object from a PSObject: the public BaseObject property, and the internal
> static Base() method. If you examine these methods in Reflector, you'll see
> that they're extremely similar, except for one important difference: if
> immediateBaseObjectIsEmpty is true, Base() will return the PSObject itself,
> while BaseObject will still return the immediate base object (in this case,
> a PSCustomObject), because it never actually checks that flag. The result is
> that things that depend directly on BaseObject -- such as, for example,
> PSObject.Equals() -- will act based on the custom object, while things that
> depend on Base() will be looking at the PSObject itself. The reason the -is
> operator returns false when you check against PSCustomObject is that
> System.Management.Automation.Parser+ComparisonExpressionNode.Execute() calls
> Base() -- you can validate this behaviour by using -is to check if it's a
> PSObject instead of a PSCustomObject, which returns true.
>
> On the other hand, when you invoke GetType(), that doesn't call either
> BaseObject or Base(). The Members property of PSObject is initialized
> directly from the object that was passed to the PSObject, even if it's a
> PSCustomObject. Gun to my head, I'd say that's why PSCustomObject exists at
> all; so the various mechanisms that examine the base object can have
> something to look at. However, the end result is that invoking an instance
> method on the resulting object goes against the actual PSCustomObject, while
> most of the other mechanisms in PSH will call Base() and therefore go
> against the wrapping PSObject.
>
> Hopefully this will help explain why you're seeing what you're seeing. I
> don't know if the bug is that GetType() returns PSCustomObject or that
> Base() returns the wrapping PSObject, but I'm pretty sure there's a bug in
> there somewhere -- this behaviour is extremely confusing.
>
> -- Ryan Milligan
>
> "RichS" <RichS@discussions.microsoft.com> wrote in message
> news:4AA3DFE8-B65A-4F02-883C-C5DC8D486216@microsoft.com...
> >I would stick with gettype() PSCustomObject is I believe a PowerShell
> > wrapper object for the underlying .NET object. gettype() will return the
> > underlying type which is what I think you are after
> > --
> > Richard Siddaway
> > Please note that all scripts are supplied "as is" and with no warranty
> > Blog: http://richardsiddaway.spaces.live.com/
> > PowerShell User Group: http://www.get-psuguk.org.uk
> >
> >
> > "Doug" wrote:
> >
> >> I do an Import-Csv on a file and get False when using the '-is
> >> [PSCustomObject]' operator the first element .
> >>
> >> Should I stick with using .GetType().Name ?
> >>
> >> PS > $data = Import-Csv test.csv
> >> PS > $data[0] | gm
> >>
> >>
> >> TypeName: System.Management.Automation.PSCustomObject
> >>
> >> Name MemberType Definition
> >> ---- ---------- ----------
> >> Equals Method System.Boolean Equals(Object obj)
> >> GetHashCode Method System.Int32 GetHashCode()
> >> GetType Method System.Type GetType()
> >> ToString Method System.String ToString()
> >> Age NoteProperty System.String Age=1
> >> Name NoteProperty System.String Name=John Doe
> >>
> >>
> >> PS > $data[0] -is [object]
> >> True
> >> PS > $data[0] -is [System.Management.Automation.PSCustomObject]
> >> False
> >> PS > $data[0].GetType().Name
> >> PSCustomObject
> >> PS > $data[0].GetType().Name -eq "PSCustomObject"
> >> True

>
>
>

My System SpecsSystem Spec