Such a
PSObject has the member
_immediateBaseObject that contains a reference to the actual object, which can by any
.NET object, that is manipulated through the PowerShell object.
PSObject, its base object and PSCustomObject
In the
source code,
PSObject has the following interesting snippets (
heavily redacted by me for brevity) that I believe shed some light on how
PSObject and
PSCustomObject play together.
In
PSObject, the field
_immediateBaseObject contains a reference to the object that a
PowerShell object is storing (via
PSObject).
If the constructor of PSObject is called with an object (public PSObject(object obj)), the reference of _immediateBaseObject is set to that object by calling CommonInitialization(obj).
However, if the constructor without argument (
public PSObject()) is used to initialize a
PSObject instance,
CommonInitialization() is called with
PSCustomObject.SelfInstance. This expression refers to the
PSCustomObject singleton(?). Thus,
_immediateBaseObject is initialized with a reference to
PSCustomObject (see also
definition of PSCustomObject).
In summary, PSCustomObject is used to intialize the base object of PSObject in absence of any other .NET object. This indicates that the PSObject is just used to store one or more NoteProperty (?).
public class PSObject : IFormattable, IComparable, ISerializable, IDynamicMetaObjectProvider
{
/// This is the main field in the class representing
/// the System.Object we are encapsulating.
private object _immediateBaseObject;
/// Initializes a new instance of PSObject with an PSCustomObject BaseObject.
public PSObject()
{
CommonInitialization(PSCustomObject.SelfInstance);
}
/// Initializes a new instance of PSObject wrapping obj (accessible through BaseObject).
public PSObject(object obj)
{
CommonInitialization(obj);
}
private void CommonInitialization(object obj)
{
if (obj is PSCustomObject)
{
this.ImmediateBaseObjectIsEmpty = true;
}
_immediateBaseObject = obj;
}
/// Gets the object we are directly wrapping.
/// If the ImmediateBaseObject is another PSObject,
/// that PSObject will be returned.
public object ImmediateBaseObject => _immediateBaseObject;
/// Gets the object we are wrapping.
/// If the ImmediateBaseObject is another PSObject, this property
/// will return its BaseObject.
public object BaseObject
{
get
{
object returnValue;
PSObject mshObj = this;
do
{
returnValue = mshObj._immediateBaseObject;
mshObj = returnValue as PSObject;
} while (mshObj != null);
return returnValue;
}
}
}
Public properties
The PSObject class exhibits six public properties:
// Gets the member collection.
public PSMemberInfoCollection<PSMemberInfo> Members …
// Gets the Property collection, or the members that are actually properties.
public PSMemberInfoCollection<PSPropertyInfo> Properties …
// Gets the Method collection, or the members that are actually methods.
public PSMemberInfoCollection<PSMethodInfo> Methods
// Gets the object we are directly wrapping.
// (If the ImmediateBaseObject is another PSObject, that PSObject will be returned.)
public object ImmediateBaseObject => _immediateBaseObject;
// Gets the object we are wrapping
// (If the ImmediateBaseObject is another PSObject, this property will return its BaseObject.)
public object BaseObject …
// Gets the type names collection initially containing the object type hierarchy.
public Collection<string> TypeNames …
PS C:\> $obj = get-date
PS C:\> $obj.psObject.Members
PS C:\> $obj.psObject.Properties
PS C:\> $obj.psObject.Methods
PS C:\> $obj.psObject.ImmediateBaseObject
PS C:\> $obj.psObject.BaseObject
PS C:\> $obj.psObject.TypeNames
TODO: fields
The class has also the following interesting fields that should eventually be described:
private WeakReference<TypeTable> _typeTable;
private AdapterSet _adapterSet;
private PSMemberInfoInternalCollection<PSMemberInfo> _instanceMembers;
private PSMemberInfoIntegratingCollection<PSMemberInfo> _members;
private PSMemberInfoIntegratingCollection<PSPropertyInfo> _properties;
private PSMemberInfoIntegratingCollection<PSMethodInfo> _methods;
private PSObjectFlags _flags;
PSMemberInfo is the base class for all members of a
PSObject.
PSPropertyInfo is the base class for all members of a
PSObject that behave like a property.
PSMethodInfo is the base class for all members of a
PSObject that behave like a method.