/********************************************************************++ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ using System.Linq; using System.Management.Automation.Language; using System.Reflection; using System.Globalization; using System.Collections.Specialized; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections; using System.ComponentModel; using System.Text; using System.Management.Automation.Internal; using Microsoft.PowerShell; using TypeTable = System.Management.Automation.Runspaces.TypeTable; #pragma warning disable 1634, 1691 // Stops compiler from warning about unknown warnings #pragma warning disable 56503 namespace System.Management.Automation { #region PSMemberInfo /// /// Enumerates all possible types of members /// [TypeConverterAttribute(typeof(LanguagePrimitives.EnumMultipleTypeConverter))] [FlagsAttribute()] public enum PSMemberTypes { /// /// An alias to another member /// AliasProperty = 1, /// /// A property defined as a reference to a method /// CodeProperty = 2, /// /// A property from the BaseObject /// Property = 4, /// /// A prorperty defined by a Name-Value pair /// NoteProperty = 8, /// /// A property defined by script language /// ScriptProperty = 16, /// /// A set of properties /// PropertySet = 32, /// /// A method from the BaseObject /// Method = 64, /// /// A method defined as a reference to another method /// CodeMethod = 128, /// /// A method defined as a script /// ScriptMethod = 256, /// /// A member that acts like a Property that takes parameters. This is not consider to be a property or a method. /// ParameterizedProperty = 512, /// /// A set of members /// MemberSet = 1024, /// /// All events /// Event = 2048, /// /// All dynamic members (where PowerShell cannot know the type of the member) /// Dynamic = 4096, /// /// All property member types /// Properties = AliasProperty | CodeProperty | Property | NoteProperty | ScriptProperty, /// /// All method member types /// Methods = CodeMethod | Method | ScriptMethod, /// /// All member types /// All = Properties | Methods | Event | PropertySet | MemberSet | ParameterizedProperty | Dynamic } /// /// Enumerator for all possible views available on a PSObject. /// [TypeConverterAttribute(typeof(LanguagePrimitives.EnumMultipleTypeConverter))] [FlagsAttribute()] public enum PSMemberViewTypes { /// /// Extended methods / properties /// Extended = 1, /// /// Adapted methods / properties /// Adapted = 2, /// /// Base methods / properties /// Base = 4, /// /// All methods / properties /// All = Extended | Adapted | Base } /// /// Match options /// [FlagsAttribute] internal enum MshMemberMatchOptions { /// /// No options /// None = 0, /// /// Hidden members should be displayed /// IncludeHidden = 1, /// /// Only include members with property set to true /// OnlySerializable = 2 } /// /// Serves as the base class for all members of an PSObject /// public abstract class PSMemberInfo { internal object instance; internal string name; internal bool ShouldSerialize { get; set; } internal virtual void ReplicateInstance(object particularInstance) { this.instance = particularInstance; } internal void SetValueNoConversion(object setValue) { PSProperty thisAsProperty = this as PSProperty; if (thisAsProperty == null) { this.Value = setValue; return; } thisAsProperty.SetAdaptedValue(setValue, false); } /// /// Initializes a new instance of an PSMemberInfo derived class /// protected PSMemberInfo() { ShouldSerialize = true; IsInstance = true; } internal void CloneBaseProperties(PSMemberInfo destiny) { destiny.name = name; destiny.IsHidden = IsHidden; destiny.IsReservedMember = IsReservedMember; destiny.IsInstance = IsInstance; destiny.instance = instance; destiny.ShouldSerialize = ShouldSerialize; } /// /// Gets the member type /// public abstract PSMemberTypes MemberType { get; } /// /// Gets the member name /// public string Name { get { return this.name; } } /// /// Allows a derived class to set the member name... /// /// protected void SetMemberName(string name) { if (string.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; } /// /// True if this is one of the reserved members /// internal bool IsReservedMember { get; set; } /// /// True if the member should be hidden when searching with PSMemberInfoInternalCollection's Match /// or enumerating a collection. /// This should not be settable as it would make the count of hidden properties in /// PSMemberInfoInternalCollection invalid. /// For now, we are carefully setting this.isHidden before adding /// the members toPSObjectMembersetCollection. In the future, we might need overload for all /// PSMemberInfo constructors to take isHidden. /// internal bool IsHidden { get; set; } /// /// True if this member has been added to the instance as opposed to /// coming from the adapter or from type data /// public bool IsInstance { get; internal set; } /// /// Gets and Sets the value of this member /// /// When getting the value of a property throws an exception. /// This exception is also thrown if the property is an and there /// is no Runspace to run the script. /// When setting the value of a property throws an exception. /// This exception is also thrown if the property is an and there /// is no Runspace to run the script. /// When some problem other then getting/setting the value happened public abstract object Value { get; set; } /// /// Gets the type of the value for this member /// /// When there was a problem getting the property public abstract string TypeNameOfValue { get; } /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public abstract PSMemberInfo Copy(); internal bool MatchesOptions(MshMemberMatchOptions options) { if (this.IsHidden && (0 == (options & MshMemberMatchOptions.IncludeHidden))) { return false; } if (!this.ShouldSerialize && (0 != (options & MshMemberMatchOptions.OnlySerializable))) { return false; } return true; } } /// /// Serves as a base class for all members that behave like properties. /// public abstract class PSPropertyInfo : PSMemberInfo { /// /// Initializes a new instance of an PSPropertyInfo derived class /// protected PSPropertyInfo() { } /// /// Gets true if this property can be set /// public abstract bool IsSettable { get; } /// /// Gets true if this property can be read /// public abstract bool IsGettable { get; } internal Exception NewSetValueException(Exception e, string errorId) { return new SetValueInvocationException(errorId, e, ExtendedTypeSystem.ExceptionWhenSetting, this.Name, e.Message); } internal Exception NewGetValueException(Exception e, string errorId) { return new GetValueInvocationException(errorId, e, ExtendedTypeSystem.ExceptionWhenGetting, this.Name, e.Message); } } /// /// Serves as an alias to another member /// /// /// It is permitted to subclass /// but there is no established scenario for doing this, nor has it been tested. /// public class PSAliasProperty : PSPropertyInfo { /// /// Returns the string representation of this property /// /// This property as a string public override string ToString() { StringBuilder returnValue = new StringBuilder(); returnValue.Append(this.Name); returnValue.Append(" = "); if (ConversionType != null) { returnValue.Append("("); returnValue.Append(ConversionType); returnValue.Append(")"); } returnValue.Append(ReferencedMemberName); return returnValue.ToString(); } /// /// Initializes a new instance of PSAliasProperty setting the name of the alias /// and the name of the member this alias refers to. /// /// name of the alias /// name of the member this alias refers to /// for invalid arguments public PSAliasProperty(string name, string referencedMemberName) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; if (String.IsNullOrEmpty(referencedMemberName)) { throw PSTraceSource.NewArgumentException("referencedMemberName"); } ReferencedMemberName = referencedMemberName; } /// /// Initializes a new instance of PSAliasProperty setting the name of the alias, /// the name of the member this alias refers to and the type to convert the referenced /// member's value. /// /// name of the alias /// name of the member this alias refers to /// the type to convert the referenced member's value /// for invalid arguments public PSAliasProperty(string name, string referencedMemberName, Type conversionType) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; if (String.IsNullOrEmpty(referencedMemberName)) { throw PSTraceSource.NewArgumentException("referencedMemberName"); } ReferencedMemberName = referencedMemberName; // conversionType is optional and can be null ConversionType = conversionType; } /// /// Gets the name of the member this alias refers to /// public string ReferencedMemberName { get; } /// /// Gets the member this alias refers to /// internal PSMemberInfo ReferencedMember { get { return this.LookupMember(ReferencedMemberName); } } /// /// Gets the the type to convert the referenced member's value. It might be /// null when no conversion is done. /// public Type ConversionType { get; private set; } #region virtual implementation /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { PSAliasProperty alias = new PSAliasProperty(name, ReferencedMemberName); alias.ConversionType = ConversionType; CloneBaseProperties(alias); return alias; } /// /// Gets the member type /// public override PSMemberTypes MemberType { get { return PSMemberTypes.AliasProperty; } } /// /// Gets the type of the value for this member /// /// /// When /// the alias has not been added to an PSObject or /// the alias has a cycle or /// an aliased member is not present /// public override string TypeNameOfValue { get { if (ConversionType != null) { return ConversionType.FullName; } return this.ReferencedMember.TypeNameOfValue; } } /// /// Gets true if this property can be set /// /// /// When /// the alias has not been added to an PSObject or /// the alias has a cycle or /// an aliased member is not presen /// public override bool IsSettable { get { PSPropertyInfo memberProperty = this.ReferencedMember as PSPropertyInfo; if (memberProperty != null) { return memberProperty.IsSettable; } return false; } } /// /// Gets true if this property can be read /// /// /// When /// the alias has not been added to an PSObject or /// the alias has a cycle or /// an aliased member is not present /// public override bool IsGettable { get { PSPropertyInfo memberProperty = this.ReferencedMember as PSPropertyInfo; if (memberProperty != null) { return memberProperty.IsGettable; } return false; } } private PSMemberInfo LookupMember(string name) { bool hasCycle; PSMemberInfo returnValue; LookupMember(name, new HashSet(StringComparer.OrdinalIgnoreCase), out returnValue, out hasCycle); if (hasCycle) { throw new ExtendedTypeSystemException( "CycleInAliasLookup", null, ExtendedTypeSystem.CycleInAlias, this.Name); } return returnValue; } private void LookupMember(string name, HashSet visitedAliases, out PSMemberInfo returnedMember, out bool hasCycle) { returnedMember = null; if (this.instance == null) { throw new ExtendedTypeSystemException("AliasLookupMemberOutsidePSObject", null, ExtendedTypeSystem.AccessMemberOutsidePSObject, name); } PSMemberInfo member = PSObject.AsPSObject(this.instance).Properties[name]; if (member == null) { throw new ExtendedTypeSystemException( "AliasLookupMemberNotPresent", null, ExtendedTypeSystem.MemberNotPresent, name); } PSAliasProperty aliasMember = member as PSAliasProperty; if (aliasMember == null) { hasCycle = false; returnedMember = member; return; } if (visitedAliases.Contains(name)) { hasCycle = true; return; } visitedAliases.Add(name); LookupMember(aliasMember.ReferencedMemberName, visitedAliases, out returnedMember, out hasCycle); } /// /// Gets and Sets the value of this member /// /// /// When /// the alias has not been added to an PSObject or /// the alias has a cycle or /// an aliased member is not present /// /// When getting the value of a property throws an exception /// When setting the value of a property throws an exception public override object Value { get { object returnValue = this.ReferencedMember.Value; if (ConversionType != null) { returnValue = LanguagePrimitives.ConvertTo(returnValue, ConversionType, CultureInfo.InvariantCulture); } return returnValue; } set { this.ReferencedMember.Value = value; } } #endregion virtual implementation } /// /// Serves as a property implemented with references to methods for getter and setter. /// /// /// It is permitted to subclass /// but there is no established scenario for doing this, nor has it been tested. /// public class PSCodeProperty : PSPropertyInfo { /// /// Returns the string representation of this property /// /// This property as a string public override string ToString() { StringBuilder returnValue = new StringBuilder(); returnValue.Append(this.TypeNameOfValue); returnValue.Append(" "); returnValue.Append(this.Name); returnValue.Append("{"); if (this.IsGettable) { returnValue.Append("get="); returnValue.Append(GetterCodeReference.Name); returnValue.Append(";"); } if (this.IsSettable) { returnValue.Append("set="); returnValue.Append(SetterCodeReference.Name); returnValue.Append(";"); } returnValue.Append("}"); return returnValue.ToString(); } /// /// Called from TypeTableUpdate before SetSetterFromTypeTable is called /// internal void SetGetterFromTypeTable(Type type, string methodName) { MethodInfo methodAsMember = null; try { methodAsMember = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase); } catch (AmbiguousMatchException) { // Ignore the AmbiguousMatchException. // We will generate error below if we cannot find exactly one match method. } if (methodAsMember == null) { throw new ExtendedTypeSystemException( "GetterFormatFromTypeTable", null, ExtendedTypeSystem.CodePropertyGetterFormat); } SetGetter(methodAsMember); } /// /// Called from TypeTableUpdate after SetGetterFromTypeTable is called /// internal void SetSetterFromTypeTable(Type type, string methodName) { MethodInfo methodAsMember = null; try { methodAsMember = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase); } catch (AmbiguousMatchException) { // Ignore the AmbiguousMatchException. // We will generate error below if we cannot find exactly one match method. } if (methodAsMember == null) { throw new ExtendedTypeSystemException( "SetterFormatFromTypeTable", null, ExtendedTypeSystem.CodePropertySetterFormat); } SetSetter(methodAsMember, GetterCodeReference); } /// /// Used from TypeTable with the internal constructor /// internal void SetGetter(MethodInfo methodForGet) { if (methodForGet == null) { GetterCodeReference = null; return; } if (!CheckGetterMethodInfo(methodForGet)) { throw new ExtendedTypeSystemException( "GetterFormat", null, ExtendedTypeSystem.CodePropertyGetterFormat); } GetterCodeReference = methodForGet; } internal static bool CheckGetterMethodInfo(MethodInfo methodForGet) { ParameterInfo[] parameters = methodForGet.GetParameters(); return methodForGet.IsPublic && methodForGet.IsStatic && methodForGet.ReturnType != typeof(void) && parameters.Length == 1 && parameters[0].ParameterType == typeof(PSObject); } /// /// Used from TypeTable with the internal constructor /// private void SetSetter(MethodInfo methodForSet, MethodInfo methodForGet) { if (methodForSet == null) { if (methodForGet == null) { throw new ExtendedTypeSystemException( "SetterAndGetterNullFormat", null, ExtendedTypeSystem.CodePropertyGetterAndSetterNull); } SetterCodeReference = null; return; } if (!CheckSetterMethodInfo(methodForSet, methodForGet)) { throw new ExtendedTypeSystemException( "SetterFormat", null, ExtendedTypeSystem.CodePropertySetterFormat); } SetterCodeReference = methodForSet; } internal static bool CheckSetterMethodInfo(MethodInfo methodForSet, MethodInfo methodForGet) { ParameterInfo[] parameters = methodForSet.GetParameters(); return methodForSet.IsPublic && methodForSet.IsStatic && methodForSet.ReturnType == typeof(void) && parameters.Length == 2 && parameters[0].ParameterType == typeof(PSObject) && (methodForGet == null || methodForGet.ReturnType == parameters[1].ParameterType); } /// /// Used from TypeTable to delay setting getter and setter /// internal PSCodeProperty(string name) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; } /// /// Initializes a new instance of the PSCodeProperty class as a read only property. /// /// name of the property /// This should be a public static non void method taking one PSObject parameter. /// if namme is null or empty or getterCodeReference is null /// if getterCodeReference doesn't have the right format. public PSCodeProperty(string name, MethodInfo getterCodeReference) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; if (getterCodeReference == null) { throw PSTraceSource.NewArgumentNullException("getterCodeReference"); } SetGetter(getterCodeReference); } /// /// Initializes a new instance of the PSCodeProperty class. Setter or getter can be null, but both cannot be null. /// /// name of the property /// This should be a public static non void method taking one PSObject parameter. /// This should be a public static void method taking 2 parameters, where the first is an PSObject. /// when methodForGet and methodForSet are null /// /// if: /// - getterCodeReference doesn't have the right format, /// - setterCodeReference doesn't have the right format, /// - both getterCodeReference and setterCodeReference are null. /// public PSCodeProperty(string name, MethodInfo getterCodeReference, MethodInfo setterCodeReference) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; if (getterCodeReference == null && setterCodeReference == null) { throw PSTraceSource.NewArgumentNullException("getterCodeReference setterCodeReference"); } SetGetter(getterCodeReference); SetSetter(setterCodeReference, getterCodeReference); } /// /// Gets the method used for the properties' getter. It might be null. /// public MethodInfo GetterCodeReference { get; private set; } /// /// Gets the method used for the properties' setter. It might be null. /// public MethodInfo SetterCodeReference { get; private set; } #region virtual implementation /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { PSCodeProperty property = new PSCodeProperty(name, GetterCodeReference, SetterCodeReference); CloneBaseProperties(property); return property; } /// /// Gets the member type /// public override PSMemberTypes MemberType { get { return PSMemberTypes.CodeProperty; } } /// /// Gets true if this property can be set /// public override bool IsSettable { get { return this.SetterCodeReference != null; } } /// /// Gets true if this property can be read /// public override bool IsGettable { get { return GetterCodeReference != null; } } /// /// Gets and Sets the value of this member /// /// When getting and there is no getter or when the getter throws an exception /// When setting and there is no setter or when the setter throws an exception public override object Value { get { if (GetterCodeReference == null) { throw new GetValueException("GetWithoutGetterFromCodePropertyValue", null, ExtendedTypeSystem.GetWithoutGetterException, this.Name); } try { return GetterCodeReference.Invoke(null, new object[1] { this.instance }); } catch (TargetInvocationException ex) { Exception inner = ex.InnerException ?? ex; throw new GetValueInvocationException("CatchFromCodePropertyGetTI", inner, ExtendedTypeSystem.ExceptionWhenGetting, this.name, inner.Message); } catch (Exception e) { if (e is GetValueException) { throw; } CommandProcessorBase.CheckForSevereException(e); throw new GetValueInvocationException("CatchFromCodePropertyGet", e, ExtendedTypeSystem.ExceptionWhenGetting, this.name, e.Message); } } set { if (SetterCodeReference == null) { throw new SetValueException("SetWithoutSetterFromCodeProperty", null, ExtendedTypeSystem.SetWithoutSetterException, this.Name); } try { SetterCodeReference.Invoke(null, new object[2] { this.instance, value }); } catch (TargetInvocationException ex) { Exception inner = ex.InnerException ?? ex; throw new SetValueInvocationException("CatchFromCodePropertySetTI", inner, ExtendedTypeSystem.ExceptionWhenSetting, this.name, inner.Message); } catch (Exception e) { if (e is SetValueException) { throw; } CommandProcessorBase.CheckForSevereException(e); throw new SetValueInvocationException("CatchFromCodePropertySet", e, ExtendedTypeSystem.ExceptionWhenSetting, this.name, e.Message); } } } /// /// Gets the type of the value for this member /// /// If there is no property getter public override string TypeNameOfValue { get { if (GetterCodeReference == null) { throw new GetValueException("GetWithoutGetterFromCodePropertyTypeOfValue", null, ExtendedTypeSystem.GetWithoutGetterException, this.Name); } return GetterCodeReference.ReturnType.FullName; } } #endregion virtual implementation } /// /// Used to access the adapted or base properties from the BaseObject /// public class PSProperty : PSPropertyInfo { /// /// Returns the string representation of this property /// /// This property as a string public override string ToString() { if (this.isDeserialized) { StringBuilder returnValue = new StringBuilder(); returnValue.Append(this.TypeNameOfValue); returnValue.Append(" {get;set;}"); return returnValue.ToString(); } Diagnostics.Assert((this.baseObject != null) && (this.adapter != null), "if it is deserialized, it should have all these properties set"); return adapter.BasePropertyToString(this); } /// /// used by the adapters to keep intermediate data used between DoGetProperty and /// DoGetValue or DoSetValue /// internal string typeOfValue; internal object serializedValue; internal bool isDeserialized; /// /// This will be either instance.adapter or instance.clrAdapter /// internal Adapter adapter; internal object adapterData; internal object baseObject; /// /// Constructs a property from a serialized value /// /// name of the property /// value of the property internal PSProperty(string name, object serializedValue) { this.isDeserialized = true; this.serializedValue = serializedValue; this.name = name; } /// /// Constructs this proprerty /// /// name of the property /// adapter used in DoGetProperty /// object passed to DoGetProperty /// adapter specific data /// for invalid arguments internal PSProperty(string name, Adapter adapter, object baseObject, object adapterData) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; this.adapter = adapter; this.adapterData = adapterData; this.baseObject = baseObject; } #region virtual implementation /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { PSProperty property = new PSProperty(this.name, this.adapter, this.baseObject, this.adapterData); CloneBaseProperties(property); property.typeOfValue = this.typeOfValue; property.serializedValue = this.serializedValue; property.isDeserialized = this.isDeserialized; return property; } /// /// Gets the member type /// public override PSMemberTypes MemberType { get { return PSMemberTypes.Property; } } private object GetAdaptedValue() { if (this.isDeserialized) { return serializedValue; } Diagnostics.Assert((this.baseObject != null) && (this.adapter != null), "if it is deserialized, it should have all these properties set"); object o = adapter.BasePropertyGet(this); return o; } internal void SetAdaptedValue(object setValue, bool shouldConvert) { if (this.isDeserialized) { serializedValue = setValue; return; } Diagnostics.Assert((this.baseObject != null) && (this.adapter != null), "if it is deserialized, it should have all these properties set"); adapter.BasePropertySet(this, setValue, shouldConvert); } /// /// Gets or sets the value of this property /// /// When getting the value of a property throws an exception /// When setting the value of a property throws an exception public override object Value { get { return GetAdaptedValue(); } set { SetAdaptedValue(value, true); } } /// /// Gets true if this property can be set /// public override bool IsSettable { get { if (this.isDeserialized) { return true; } Diagnostics.Assert((this.baseObject != null) && (this.adapter != null), "if it is deserialized, it should have all these properties set"); return adapter.BasePropertyIsSettable(this); } } /// /// Gets true if this property can be read /// public override bool IsGettable { get { if (this.isDeserialized) { return true; } Diagnostics.Assert((this.baseObject != null) && (this.adapter != null), "if it is deserialized, it should have all these properties set"); return adapter.BasePropertyIsGettable(this); } } /// /// Gets the type of the value for this member /// public override string TypeNameOfValue { get { if (this.isDeserialized) { if (serializedValue == null) { return String.Empty; } PSObject serializedValueAsPSObject = serializedValue as PSObject; if (serializedValueAsPSObject != null) { var typeNames = serializedValueAsPSObject.InternalTypeNames; if ((typeNames != null) && (typeNames.Count >= 1)) { // type name at 0-th index is the most specific type (i.e. deserialized.system.io.directoryinfo) // type names at other indices are less specific (i.e. deserialized.system.object) return typeNames[0]; } } return serializedValue.GetType().FullName; } Diagnostics.Assert((this.baseObject != null) && (this.adapter != null), "if it is deserialized, it should have all these properties set"); return adapter.BasePropertyType(this); } } #endregion virtual implementation } /// /// A property created by a user-defined PSPropertyAdapter /// public class PSAdaptedProperty : PSProperty { /// /// Creates a property for the given base object /// /// name of the property /// an adapter can use this object to keep any arbitrary data it needs /// for invalid arguments public PSAdaptedProperty(string name, object tag) : base(name, null, null, tag) { // // Note that the constructor sets the adapter and base object to null; the ThirdPartyAdapter managing this property must set these values // } internal PSAdaptedProperty(string name, Adapter adapter, object baseObject, object adapterData) : base(name, adapter, baseObject, adapterData) { } /// /// Copy an adapted property. /// public override PSMemberInfo Copy() { PSAdaptedProperty property = new PSAdaptedProperty(this.name, this.adapter, this.baseObject, this.adapterData); CloneBaseProperties(property); property.typeOfValue = this.typeOfValue; property.serializedValue = this.serializedValue; property.isDeserialized = this.isDeserialized; return property; } /// /// Gets the object the property belongs to /// public object BaseObject { get { return this.baseObject; } } /// /// Gets the data attached to this property /// public object Tag { get { return this.adapterData; } } } /// /// Serves as a property that is a simple name-value pair. /// public class PSNoteProperty : PSPropertyInfo { /// /// Returns the string representation of this property /// /// This property as a string public override string ToString() { StringBuilder returnValue = new StringBuilder(); returnValue.Append(GetDisplayTypeNameOfValue(this.Value)); returnValue.Append(" "); returnValue.Append(this.Name); returnValue.Append("="); returnValue.Append(this.noteValue == null ? "null" : this.noteValue.ToString()); return returnValue.ToString(); } internal object noteValue; /// /// Initiializes a new instance of the PSNoteProperty class. /// /// name of the property /// value of the property /// for an empty or null name public PSNoteProperty(string name, object value) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; // value can be null this.noteValue = value; } #region virtual implementation /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { PSNoteProperty property = new PSNoteProperty(this.name, this.noteValue); CloneBaseProperties(property); return property; } /// /// Gets PSMemberTypes.NoteProperty /// public override PSMemberTypes MemberType { get { return PSMemberTypes.NoteProperty; } } /// /// Gets true since the value of an PSNoteProperty can always be set /// public override bool IsSettable { get { return this.IsInstance; } } /// /// Gets true since the value of an PSNoteProperty can always be obtained /// public override bool IsGettable { get { return true; } } /// /// Gets or sets the value of this property /// public override object Value { get { return this.noteValue; } set { if (!this.IsInstance) { throw new SetValueException("ChangeValueOfStaticNote", null, ExtendedTypeSystem.ChangeStaticMember, this.Name); } this.noteValue = value; } } /// /// Gets the type of the value for this member /// public override string TypeNameOfValue { get { object val = this.Value; if (val == null) { return typeof(object).FullName; } PSObject valAsPSObject = val as PSObject; if (valAsPSObject != null) { var typeNames = valAsPSObject.InternalTypeNames; if ((typeNames != null) && (typeNames.Count >= 1)) { // type name at 0-th index is the most specific type (i.e. system.string) // type names at other indices are less specific (i.e. system.object) return typeNames[0]; } } return val.GetType().FullName; } } #endregion virtual implementation internal static string GetDisplayTypeNameOfValue(object val) { string displayTypeName = null; PSObject valAsPSObject = val as PSObject; if (valAsPSObject != null) { var typeNames = valAsPSObject.InternalTypeNames; if ((typeNames != null) && (typeNames.Count >= 1)) { displayTypeName = typeNames[0]; } } if (string.IsNullOrEmpty(displayTypeName)) { displayTypeName = val == null ? "object" : ToStringCodeMethods.Type(val.GetType(), dropNamespaces: true); } return displayTypeName; } } /// /// Serves as a property that is a simple name-value pair. /// /// /// It is permitted to subclass /// but there is no established scenario for doing this, nor has it been tested. /// public class PSVariableProperty : PSNoteProperty { /// /// Returns the string representation of this property /// /// This property as a string public override string ToString() { StringBuilder returnValue = new StringBuilder(); returnValue.Append(GetDisplayTypeNameOfValue(_variable.Value)); returnValue.Append(" "); returnValue.Append(_variable.Name); returnValue.Append("="); returnValue.Append(_variable.Value ?? "null"); return returnValue.ToString(); } internal PSVariable _variable; /// /// Initiializes a new instance of the PSVariableProperty class. This is /// a subclass of the NoteProperty that wraps a variable instead of a simple value. /// /// The variable to wrap /// for an empty or null name public PSVariableProperty(PSVariable variable) : base(variable != null ? variable.Name : null, null) { if (variable == null) { throw PSTraceSource.NewArgumentException("variable"); } _variable = variable; } #region virtual implementation /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo, /// Note that it returns another reference to the variable, not a reference /// to a new variable... /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { PSNoteProperty property = new PSVariableProperty(_variable); CloneBaseProperties(property); return property; } /// /// Gets PSMemberTypes.NoteProperty /// public override PSMemberTypes MemberType { get { return PSMemberTypes.NoteProperty; } } /// /// True if the underlying variable is settable... /// public override bool IsSettable { get { return (_variable.Options & (ScopedItemOptions.Constant | ScopedItemOptions.ReadOnly)) == ScopedItemOptions.None; } } /// /// Gets true since the value of an PSNoteProperty can always be obtained /// public override bool IsGettable { get { return true; } } /// /// Gets or sets the value of this property /// public override object Value { get { return _variable.Value; } set { if (!this.IsInstance) { throw new SetValueException("ChangeValueOfStaticNote", null, ExtendedTypeSystem.ChangeStaticMember, this.Name); } _variable.Value = value; } } /// /// Gets the type of the value for this member /// public override string TypeNameOfValue { get { object val = _variable.Value; if (val == null) { return typeof(object).FullName; } PSObject valAsPSObject = val as PSObject; if (valAsPSObject != null) { var typeNames = valAsPSObject.InternalTypeNames; if ((typeNames != null) && (typeNames.Count >= 1)) { // type name at 0-th index is the most specific type (i.e. system.string) // type names at other indices are less specific (i.e. system.object) return typeNames[0]; } } return val.GetType().FullName; } } #endregion virtual implementation } /// /// Serves as a property implemented with getter and setter scripts. /// /// /// It is permitted to subclass /// but there is no established scenario for doing this, nor has it been tested. /// public class PSScriptProperty : PSPropertyInfo { /// /// Returns the string representation of this property /// /// This property as a string public override string ToString() { StringBuilder returnValue = new StringBuilder(); returnValue.Append(this.TypeNameOfValue); returnValue.Append(" "); returnValue.Append(this.Name); returnValue.Append(" {"); if (this.IsGettable) { returnValue.Append("get="); returnValue.Append(this.GetterScript.ToString()); returnValue.Append(";"); } if (this.IsSettable) { returnValue.Append("set="); returnValue.Append(this.SetterScript.ToString()); returnValue.Append(";"); } returnValue.Append("}"); return returnValue.ToString(); } private Nullable _languageMode; private string _getterScriptText; private ScriptBlock _getterScript; private string _setterScriptText; private ScriptBlock _setterScript; private bool _shouldCloneOnAccess; /// /// Gets the script used for the property getter. It might be null. /// public ScriptBlock GetterScript { get { // If we don't have a script block for the getter, see if we // have the text for it (to support delayed script compilation). if ((_getterScript == null) && (_getterScriptText != null)) { _getterScript = ScriptBlock.Create(_getterScriptText); if (_languageMode.HasValue) { _getterScript.LanguageMode = _languageMode; } _getterScript.DebuggerStepThrough = true; } if (_getterScript == null) { return null; } if (_shouldCloneOnAccess) { // returning a clone as TypeTable might be shared between multiple // runspaces and ScriptBlock is not shareable. We decided to // Clone as needed instead of Cloning whenever a shared TypeTable is // attached to a Runspace to save on Memory. ScriptBlock newGetterScript = _getterScript.Clone(); newGetterScript.LanguageMode = _getterScript.LanguageMode; return newGetterScript; } else { return _getterScript; } } } /// /// Gets the script used for the property setter. It might be null. /// public ScriptBlock SetterScript { get { // If we don't have a script block for the setter, see if we // have the text for it (to support delayed script compilation). if ((_setterScript == null) && (_setterScriptText != null)) { _setterScript = ScriptBlock.Create(_setterScriptText); if (_languageMode.HasValue) { _setterScript.LanguageMode = _languageMode; } _setterScript.DebuggerStepThrough = true; } if (_setterScript == null) { return null; } if (_shouldCloneOnAccess) { // returning a clone as TypeTable might be shared between multiple // runspaces and ScriptBlock is not shareable. We decided to // Clone as needed instead of Cloning whenever a shared TypeTable is // attached to a Runspace to save on Memory. ScriptBlock newSetterScript = _setterScript.Clone(); newSetterScript.LanguageMode = _setterScript.LanguageMode; return newSetterScript; } else { return _setterScript; } } } /// /// Initializes an instance of the PSScriptProperty class as a read only property. /// /// name of the property /// script to be used for the property getter. $this will be this PSObject. /// for invalid arguments public PSScriptProperty(string name, ScriptBlock getterScript) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; if (getterScript == null) { throw PSTraceSource.NewArgumentNullException("getterScript"); } _getterScript = getterScript; } /// /// Initializes an instance of the PSScriptProperty class as a read only /// property. getterScript or setterScript can be null, but not both. /// /// Name of this property /// script to be used for the property getter. $this will be this PSObject. /// script to be used for the property setter. $this will be this PSObject and $args(1) will be the value to set. /// for invalid arguments public PSScriptProperty(string name, ScriptBlock getterScript, ScriptBlock setterScript) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; if (getterScript == null && setterScript == null) { // we only do not allow both getterScript and setterScript to be null throw PSTraceSource.NewArgumentException("getterScript setterScript"); } if (getterScript != null) { getterScript.DebuggerStepThrough = true; } if (setterScript != null) { setterScript.DebuggerStepThrough = true; } _getterScript = getterScript; _setterScript = setterScript; } /// /// Initializes an instance of the PSScriptProperty class as a read only /// property, using the text of the properties to support lazy initialization. /// /// Name of this property /// script to be used for the property getter. $this will be this PSObject. /// script to be used for the property setter. $this will be this PSObject and $args(1) will be the value to set. /// Language mode to be used during script block evaluation. /// for invalid arguments internal PSScriptProperty(string name, string getterScript, string setterScript, Nullable languageMode) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; if (getterScript == null && setterScript == null) { // we only do not allow both getterScript and setterScript to be null throw PSTraceSource.NewArgumentException("getterScript setterScript"); } _getterScriptText = getterScript; _setterScriptText = setterScript; _languageMode = languageMode; } internal PSScriptProperty(string name, ScriptBlock getterScript, ScriptBlock setterScript, bool shouldCloneOnAccess) : this(name, getterScript, setterScript) { _shouldCloneOnAccess = shouldCloneOnAccess; } internal PSScriptProperty(string name, string getterScript, string setterScript, Nullable languageMode, bool shouldCloneOnAccess) : this(name, getterScript, setterScript, languageMode) { _shouldCloneOnAccess = shouldCloneOnAccess; } #region virtual implementation /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { PSScriptProperty property; property = new PSScriptProperty(name, this.GetterScript, this.SetterScript); property._shouldCloneOnAccess = _shouldCloneOnAccess; CloneBaseProperties(property); return property; } /// /// Gets the member type /// public override PSMemberTypes MemberType { get { return PSMemberTypes.ScriptProperty; } } /// /// Gets true if this property can be set /// public override bool IsSettable { get { return this.SetterScript != null; } } /// /// Gets true if this property can be read /// public override bool IsGettable { get { return this.GetterScript != null; } } /// /// Gets and Sets the value of this property /// /// When getting and there is no getter, /// when the getter throws an exception or when there is no Runspace to run the script. /// /// When setting and there is no setter, /// when the setter throws an exception or when there is no Runspace to run the script. public override object Value { get { if (this.GetterScript == null) { throw new GetValueException("GetWithoutGetterFromScriptPropertyValue", null, ExtendedTypeSystem.GetWithoutGetterException, this.Name); } return InvokeGetter(this.instance); } set { if (this.SetterScript == null) { throw new SetValueException("SetWithoutSetterFromScriptProperty", null, ExtendedTypeSystem.SetWithoutSetterException, this.Name); } InvokeSetter(this.instance, value); } } internal object InvokeSetter(object scriptThis, object value) { try { SetterScript.DoInvokeReturnAsIs( useLocalScope: true, errorHandlingBehavior: ScriptBlock.ErrorHandlingBehavior.WriteToExternalErrorPipe, dollarUnder: AutomationNull.Value, input: AutomationNull.Value, scriptThis: scriptThis, args: new object[] { value }); return value; } catch (SessionStateOverflowException e) { throw NewSetValueException(e, "ScriptSetValueSessionStateOverflowException"); } catch (RuntimeException e) { throw NewSetValueException(e, "ScriptSetValueRuntimeException"); } catch (TerminateException) { // The debugger is terminating the execution; let the exception bubble up throw; } catch (FlowControlException e) { throw NewSetValueException(e, "ScriptSetValueFlowControlException"); } catch (PSInvalidOperationException e) { throw NewSetValueException(e, "ScriptSetValueInvalidOperationException"); } } internal object InvokeGetter(object scriptThis) { try { return GetterScript.DoInvokeReturnAsIs( useLocalScope: true, errorHandlingBehavior: ScriptBlock.ErrorHandlingBehavior.SwallowErrors, dollarUnder: AutomationNull.Value, input: AutomationNull.Value, scriptThis: scriptThis, args: Utils.EmptyArray()); } catch (SessionStateOverflowException e) { throw NewGetValueException(e, "ScriptGetValueSessionStateOverflowException"); } catch (RuntimeException e) { throw NewGetValueException(e, "ScriptGetValueRuntimeException"); } catch (TerminateException) { // The debugger is terminating the execution; let the exception bubble up throw; } catch (FlowControlException e) { throw NewGetValueException(e, "ScriptGetValueFlowControlException"); } catch (PSInvalidOperationException e) { throw NewGetValueException(e, "ScriptgetValueInvalidOperationException"); } } /// /// Gets the type of the value for this member. Currently this always returns typeof(object).FullName. /// public override string TypeNameOfValue { get { if ((this.GetterScript != null) && (this.GetterScript.OutputType.Count > 0)) { return this.GetterScript.OutputType[0].Name; } else { return typeof(object).FullName; } } } #endregion virtual implementation } internal class PSMethodInvocationConstraints { internal PSMethodInvocationConstraints( Type methodTargetType, Type[] parameterTypes) { this.MethodTargetType = methodTargetType; _parameterTypes = parameterTypes; } /// /// If null then there are no constraints /// public Type MethodTargetType { get; private set; } /// /// If null then there are no constraints /// public IEnumerable ParameterTypes { get { return _parameterTypes; } } private readonly Type[] _parameterTypes; internal static bool EqualsForCollection(ICollection xs, ICollection ys) { if (xs == null) { return ys == null; } if (ys == null) { return false; } if (xs.Count != ys.Count) { return false; } return xs.SequenceEqual(ys); } // TODO: IEnumerable genericTypeParameters { get; private set; } public bool Equals(PSMethodInvocationConstraints other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } if (other.MethodTargetType != this.MethodTargetType) { return false; } if (!EqualsForCollection(_parameterTypes, other._parameterTypes)) { return false; } return true; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != typeof(PSMethodInvocationConstraints)) { return false; } return Equals((PSMethodInvocationConstraints)obj); } public override int GetHashCode() { // algorithm based on http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode unchecked { int result = 61; result = result * 397 + (MethodTargetType != null ? MethodTargetType.GetHashCode() : 0); result = result * 397 + ParameterTypes.SequenceGetHashCode(); return result; } } public override string ToString() { StringBuilder sb = new StringBuilder(); string separator = ""; if (MethodTargetType != null) { sb.Append("this: "); sb.Append(ToStringCodeMethods.Type(MethodTargetType, dropNamespaces: true)); separator = " "; } if (_parameterTypes != null) { sb.Append(separator); sb.Append("args: "); separator = ""; foreach (var p in _parameterTypes) { sb.Append(separator); sb.Append(ToStringCodeMethods.Type(p, dropNamespaces: true)); separator = ", "; } } if (sb.Length == 0) { sb.Append(""); } return sb.ToString(); } } /// /// Serves as a base class for all members that behave like methods. /// public abstract class PSMethodInfo : PSMemberInfo { /// /// Initializes a new instance of a class derived from PSMethodInfo. /// protected PSMethodInfo() { } /// /// Invokes the appropriate method overload for the given arguments and returns its result. /// /// arguments to the method /// return value from the method /// if arguments is null /// For problems finding an appropriate method for the arguments /// For exceptions invoking the method. /// This exception is also thrown for an when there is no Runspace to run the script. public abstract object Invoke(params object[] arguments); /// /// Gets a list of all the overloads for this method /// public abstract Collection OverloadDefinitions { get; } #region virtual implementation /// /// Gets the value of this member. The getter returns the PSMethodInfo itself. /// /// When setting the member /// /// This is not the returned value of the method even for Methods with no arguments. /// The getter returns this (the PSMethodInfo itself). The setter is not supported. /// public sealed override object Value { get { return this; } set { throw new ExtendedTypeSystemException("CannotChangePSMethodInfoValue", null, ExtendedTypeSystem.CannotSetValueForMemberType, this.GetType().FullName); } } #endregion virtual implementation } /// /// Serves as a method implemented with a reference to another method. /// /// /// It is permitted to subclass /// but there is no established scenario for doing this, nor has it been tested. /// public class PSCodeMethod : PSMethodInfo { /// /// Returns the string representation of this member /// /// This property as a string public override string ToString() { StringBuilder returnValue = new StringBuilder(); foreach (string overload in OverloadDefinitions) { returnValue.Append(overload); returnValue.Append(", "); } returnValue.Remove(returnValue.Length - 2, 2); return returnValue.ToString(); } private MethodInformation[] _codeReferenceMethodInformation; internal static bool CheckMethodInfo(MethodInfo method) { ParameterInfo[] parameters = method.GetParameters(); return method.IsStatic && method.IsPublic && parameters.Length != 0 && parameters[0].ParameterType == typeof(PSObject); } internal void SetCodeReference(Type type, string methodName) { MethodInfo methodAsMember = null; try { methodAsMember = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase); } catch (AmbiguousMatchException) { // Ignore the AmbiguousMatchException. // We will generate error below if we cannot find exactly one match method. } if (methodAsMember == null) { throw new ExtendedTypeSystemException("WrongMethodFormatFromTypeTable", null, ExtendedTypeSystem.CodeMethodMethodFormat); } CodeReference = methodAsMember; if (!CheckMethodInfo(CodeReference)) { throw new ExtendedTypeSystemException("WrongMethodFormat", null, ExtendedTypeSystem.CodeMethodMethodFormat); } } /// /// Used from TypeTable /// internal PSCodeMethod(string name) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; } /// /// Initializes a new instance of the PSCodeMethod class. /// /// name of the property /// this should be a public static method where the first parameter is an PSObject. /// for invalid arguments /// if the codeReference does not have the right format public PSCodeMethod(string name, MethodInfo codeReference) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } if (codeReference == null) { throw PSTraceSource.NewArgumentNullException("codeReference"); } if (!CheckMethodInfo(codeReference)) { throw new ExtendedTypeSystemException("WrongMethodFormat", null, ExtendedTypeSystem.CodeMethodMethodFormat); } this.name = name; CodeReference = codeReference; } /// /// Gets the method referenced by this PSCodeMethod /// public MethodInfo CodeReference { get; private set; } #region virtual implementation /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { PSCodeMethod member = new PSCodeMethod(name, CodeReference); CloneBaseProperties(member); return member; } /// /// Gets the member type /// public override PSMemberTypes MemberType { get { return PSMemberTypes.CodeMethod; } } /// /// Invokes CodeReference method and returns its results. /// /// arguments to the method /// return value from the method /// if arguments is null /// /// When /// could CodeReference cannot match the given argument count or /// could not convert an argument to the type required /// /// For exceptions invoking the CodeReference public override object Invoke(params object[] arguments) { if (arguments == null) { throw PSTraceSource.NewArgumentNullException("arguments"); } object[] newArguments = new object[arguments.Length + 1]; newArguments[0] = this.instance; for (int i = 0; i < arguments.Length; i++) { newArguments[i + 1] = arguments[i]; } if (_codeReferenceMethodInformation == null) { _codeReferenceMethodInformation = DotNetAdapter.GetMethodInformationArray(new[] { CodeReference }); } object[] convertedArguments; Adapter.GetBestMethodAndArguments(CodeReference.Name, _codeReferenceMethodInformation, newArguments, out convertedArguments); return DotNetAdapter.AuxiliaryMethodInvoke(null, convertedArguments, _codeReferenceMethodInformation[0], newArguments); } /// /// Gets the definition for CodeReference /// public override Collection OverloadDefinitions { get { return new Collection { DotNetAdapter.GetMethodInfoOverloadDefinition(null, CodeReference, 0) }; } } /// /// Gets the type of the value for this member. Currently this always returns typeof(PSCodeMethod).FullName. /// public override string TypeNameOfValue { get { return typeof(PSCodeMethod).FullName; } } #endregion virtual implementation } /// /// Serves as a method implemented with a script /// /// /// It is permitted to subclass /// but there is no established scenario for doing this, nor has it been tested. /// public class PSScriptMethod : PSMethodInfo { /// /// Returns the string representation of this member /// /// This property as a string public override string ToString() { StringBuilder returnValue = new StringBuilder(); returnValue.Append(this.TypeNameOfValue); returnValue.Append(" "); returnValue.Append(this.Name); returnValue.Append("();"); return returnValue.ToString(); } private ScriptBlock _script; private bool _shouldCloneOnAccess; /// /// Gets the script implementing this PSScriptMethod /// public ScriptBlock Script { get { if (_shouldCloneOnAccess) { // returning a clone as TypeTable might be shared between multiple // runspaces and ScriptBlock is not shareable. We decided to // Clone as needed instead of Cloning whenever a shared TypeTable is // attached to a Runspace to save on Memory. ScriptBlock newScript = _script.Clone(); newScript.LanguageMode = _script.LanguageMode; return newScript; } else { return _script; } } } /// /// Initializes a new instance of PSScriptMethod /// /// name of the method /// script to be used when calling the method. /// for invalid arguments public PSScriptMethod(string name, ScriptBlock script) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; if (script == null) { throw PSTraceSource.NewArgumentNullException("script"); } _script = script; } /// /// /// /// /// /// /// Used by TypeTable. /// TypeTable might be shared between multiple runspaces and /// ScriptBlock is not shareable. We decided to Clone as needed /// instead of Cloning whenever a shared TypeTable is attached /// to a Runspace to save on Memory. /// internal PSScriptMethod(string name, ScriptBlock script, bool shouldCloneOnAccess) : this(name, script) { _shouldCloneOnAccess = shouldCloneOnAccess; } #region virtual implementation /// /// Invokes Script method and returns its results. /// /// arguments to the method /// return value from the method /// if arguments is null /// For exceptions invoking the Script or if there is no Runspace to run the script. public override object Invoke(params object[] arguments) { if (arguments == null) { throw PSTraceSource.NewArgumentNullException("arguments"); } return InvokeScript(Name, _script, this.instance, arguments); } internal static object InvokeScript(string methodName, ScriptBlock script, object @this, object[] arguments) { try { return script.DoInvokeReturnAsIs( useLocalScope: true, errorHandlingBehavior: ScriptBlock.ErrorHandlingBehavior.WriteToExternalErrorPipe, dollarUnder: AutomationNull.Value, input: AutomationNull.Value, scriptThis: @this, args: arguments); } catch (SessionStateOverflowException e) { throw new MethodInvocationException( "ScriptMethodSessionStateOverflowException", e, ExtendedTypeSystem.MethodInvocationException, methodName, arguments.Length, e.Message); } catch (RuntimeException e) { throw new MethodInvocationException( "ScriptMethodRuntimeException", e, ExtendedTypeSystem.MethodInvocationException, methodName, arguments.Length, e.Message); } catch (TerminateException) { // The debugger is terminating the execution; let the exception bubble up throw; } catch (FlowControlException e) { throw new MethodInvocationException( "ScriptMethodFlowControlException", e, ExtendedTypeSystem.MethodInvocationException, methodName, arguments.Length, e.Message); } catch (PSInvalidOperationException e) { throw new MethodInvocationException( "ScriptMethodInvalidOperationException", e, ExtendedTypeSystem.MethodInvocationException, methodName, arguments.Length, e.Message); } } /// /// Gets a list of all the overloads for this method /// public override Collection OverloadDefinitions { get { Collection retValue = new Collection(); retValue.Add(this.ToString()); return retValue; } } /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { PSScriptMethod method; method = new PSScriptMethod(this.name, _script); method._shouldCloneOnAccess = _shouldCloneOnAccess; CloneBaseProperties(method); return method; } /// /// Gets the member type /// public override PSMemberTypes MemberType { get { return PSMemberTypes.ScriptMethod; } } /// /// Gets the type of the value for this member. Currently this always returns typeof(object).FullName. /// public override string TypeNameOfValue { get { return typeof(object).FullName; } } #endregion virtual implementation } /// /// Used to access the adapted or base methods from the BaseObject /// /// /// It is permitted to subclass /// but there is no established scenario for doing this, nor has it been tested. /// public class PSMethod : PSMethodInfo { internal override void ReplicateInstance(object particularInstance) { base.ReplicateInstance(particularInstance); baseObject = particularInstance; } /// /// Returns the string representation of this member /// /// This property as a string public override string ToString() { return _adapter.BaseMethodToString(this); } internal object adapterData; private Adapter _adapter; internal object baseObject; /// /// Constructs this method /// /// name /// adapter to be used invoking /// baseObject for the methods /// adapterData from adapter.GetMethodData /// for invalid arguments internal PSMethod(string name, Adapter adapter, object baseObject, object adapterData) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; this.adapterData = adapterData; _adapter = adapter; this.baseObject = baseObject; } /// /// Constructs a PSMethod /// /// name /// adapter to be used invoking /// baseObject for the methods /// adapterData from adapter.GetMethodData /// true if this member is a special member, false otherwise. /// true if this member is hidden, false otherwise. /// for invalid arguments internal PSMethod(string name, Adapter adapter, object baseObject, object adapterData, bool isSpecial, bool isHidden) : this(name, adapter, baseObject, adapterData) { this.IsSpecial = isSpecial; this.IsHidden = isHidden; } #region virtual implementation /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { PSMethod member = new PSMethod(this.name, _adapter, this.baseObject, this.adapterData, this.IsSpecial, this.IsHidden); CloneBaseProperties(member); return member; } /// /// Gets the member type /// public override PSMemberTypes MemberType { get { return PSMemberTypes.Method; } } /// /// Invokes the appropriate method overload for the given arguments and returns its result. /// /// arguments to the method /// return value from the method /// if arguments is null /// For problems finding an appropriate method for the arguments /// For exceptions invoking the method public override object Invoke(params object[] arguments) { return this.Invoke(null, arguments); } /// /// Invokes the appropriate method overload for the given arguments and returns its result. /// /// constraints /// arguments to the method /// return value from the method /// if arguments is null /// For problems finding an appropriate method for the arguments /// For exceptions invoking the method internal object Invoke(PSMethodInvocationConstraints invocationConstraints, params object[] arguments) { if (arguments == null) { throw PSTraceSource.NewArgumentNullException("arguments"); } return _adapter.BaseMethodInvoke(this, invocationConstraints, arguments); } /// /// Gets a list of all the overloads for this method /// public override Collection OverloadDefinitions { get { return _adapter.BaseMethodDefinitions(this); } } /// /// Gets the type of the value for this member. This always returns typeof(PSMethod).FullName. /// public override string TypeNameOfValue { get { return typeof(PSMethod).FullName; } } #endregion virtual implementation /// /// True if the method is a special method like GET/SET property accessor methods. /// internal bool IsSpecial { get; private set; } } /// /// Used to access parameterized properties from the BaseObject /// /// /// It is permitted to subclass /// but there is no established scenario for doing this, nor has it been tested. /// public class PSParameterizedProperty : PSMethodInfo { /// /// Returns the string representation of this member /// /// This property as a string public override string ToString() { Diagnostics.Assert((this.baseObject != null) && (this.adapter != null) && (this.adapterData != null), "it should have all these properties set"); return this.adapter.BaseParameterizedPropertyToString(this); } internal Adapter adapter; internal object adapterData; internal object baseObject; /// /// Constructs this parameterized proprerty /// /// name of the property /// adapter used in DoGetMethod /// object passed to DoGetMethod /// adapter specific data /// for invalid arguments internal PSParameterizedProperty(string name, Adapter adapter, object baseObject, object adapterData) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; this.adapter = adapter; this.adapterData = adapterData; this.baseObject = baseObject; } internal PSParameterizedProperty(string name) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; } /// /// Gets true if this property can be set /// public bool IsSettable { get { return adapter.BaseParameterizedPropertyIsSettable(this); } } /// /// Gets true if this property can be read /// public bool IsGettable { get { return adapter.BaseParameterizedPropertyIsGettable(this); } } #region virtual implementation /// /// Invokes the getter method and returns its result /// /// arguments to the method /// return value from the method /// if arguments is null /// When getting the value of a property throws an exception public override object Invoke(params object[] arguments) { if (arguments == null) { throw PSTraceSource.NewArgumentNullException("arguments"); } return this.adapter.BaseParameterizedPropertyGet(this, arguments); } /// /// Invokes the setter method /// /// value to set this property with /// arguments to the method /// if arguments is null /// When setting the value of a property throws an exception public void InvokeSet(object valueToSet, params object[] arguments) { if (arguments == null) { throw PSTraceSource.NewArgumentNullException("arguments"); } this.adapter.BaseParameterizedPropertySet(this, valueToSet, arguments); } /// /// Returns a collection of the definitions for this property /// public override Collection OverloadDefinitions { get { return adapter.BaseParameterizedPropertyDefinitions(this); } } /// /// Gets the type of the value for this member. /// public override string TypeNameOfValue { get { return adapter.BaseParameterizedPropertyType(this); } } /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { PSParameterizedProperty property = new PSParameterizedProperty(this.name, this.adapter, this.baseObject, this.adapterData); CloneBaseProperties(property); return property; } /// /// Gets the member type /// public override PSMemberTypes MemberType { get { return PSMemberTypes.ParameterizedProperty; } } #endregion virtual implementation } /// /// Serves as a set of members /// public class PSMemberSet : PSMemberInfo { internal override void ReplicateInstance(object particularInstance) { base.ReplicateInstance(particularInstance); foreach (var member in Members) { member.ReplicateInstance(particularInstance); } } /// /// Returns the string representation of this member /// /// This property as a string public override string ToString() { StringBuilder returnValue = new StringBuilder(); returnValue.Append(" {"); foreach (PSMemberInfo member in this.Members) { returnValue.Append(member.Name); returnValue.Append(", "); } if (returnValue.Length > 2) { returnValue.Remove(returnValue.Length - 2, 2); } returnValue.Insert(0, this.Name); returnValue.Append("}"); return returnValue.ToString(); } private PSMemberInfoIntegratingCollection _members; private PSMemberInfoIntegratingCollection _properties; private PSMemberInfoIntegratingCollection _methods; internal PSMemberInfoInternalCollection internalMembers; private PSObject _constructorPSObject; private static Collection> s_emptyMemberCollection = new Collection>(); private static Collection> s_emptyMethodCollection = new Collection>(); private static Collection> s_emptyPropertyCollection = new Collection>(); /// /// Initializes a new instance of PSMemberSet with no initial members /// /// name for the member set /// for invalid arguments public PSMemberSet(string name) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; this.internalMembers = new PSMemberInfoInternalCollection(); _members = new PSMemberInfoIntegratingCollection(this, s_emptyMemberCollection); _properties = new PSMemberInfoIntegratingCollection(this, s_emptyPropertyCollection); _methods = new PSMemberInfoIntegratingCollection(this, s_emptyMethodCollection); } /// /// Initializes a new instance of PSMemberSet with all the initial members in /// /// name for the member set /// members in the member set /// for invalid arguments public PSMemberSet(string name, IEnumerable members) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; if (members == null) { throw PSTraceSource.NewArgumentNullException("members"); } this.internalMembers = new PSMemberInfoInternalCollection(); foreach (PSMemberInfo member in members) { if (member == null) { throw PSTraceSource.NewArgumentNullException("members"); } this.internalMembers.Add(member.Copy()); } _members = new PSMemberInfoIntegratingCollection(this, s_emptyMemberCollection); _properties = new PSMemberInfoIntegratingCollection(this, s_emptyPropertyCollection); _methods = new PSMemberInfoIntegratingCollection(this, s_emptyMethodCollection); } private static Collection> s_typeMemberCollection = GetTypeMemberCollection(); private static Collection> s_typeMethodCollection = GetTypeMethodCollection(); private static Collection> s_typePropertyCollection = GetTypePropertyCollection(); private static Collection> GetTypeMemberCollection() { Collection> returnValue = new Collection>(); returnValue.Add(new CollectionEntry( PSObject.TypeTableGetMembersDelegate, PSObject.TypeTableGetMemberDelegate, true, true, "type table members")); return returnValue; } private static Collection> GetTypeMethodCollection() { Collection> returnValue = new Collection>(); returnValue.Add(new CollectionEntry( PSObject.TypeTableGetMembersDelegate, PSObject.TypeTableGetMemberDelegate, true, true, "type table members")); return returnValue; } private static Collection> GetTypePropertyCollection() { Collection> returnValue = new Collection>(); returnValue.Add(new CollectionEntry( PSObject.TypeTableGetMembersDelegate, PSObject.TypeTableGetMemberDelegate, true, true, "type table members")); return returnValue; } /// /// Used to create the Extended MemberSet /// /// name of the memberSet /// object associated with this memberset /// for invalid arguments internal PSMemberSet(string name, PSObject mshObject) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; if (mshObject == null) { throw PSTraceSource.NewArgumentNullException("mshObject"); } _constructorPSObject = mshObject; this.internalMembers = mshObject.InstanceMembers; _members = new PSMemberInfoIntegratingCollection(this, s_typeMemberCollection); _properties = new PSMemberInfoIntegratingCollection(this, s_typePropertyCollection); _methods = new PSMemberInfoIntegratingCollection(this, s_typeMethodCollection); } internal bool inheritMembers = true; /// /// Gets a flag indicating whether the memberset will inherit members of the memberset /// of the same name in the "parent" class. /// public bool InheritMembers { get { return this.inheritMembers; } } /// /// Gets the internal member collection /// internal virtual PSMemberInfoInternalCollection InternalMembers { get { return this.internalMembers; } } /// /// Gets the member collection /// public PSMemberInfoCollection Members { get { return _members; } } /// /// Gets the Property collection, or the members that are actually properties. /// public PSMemberInfoCollection Properties { get { return _properties; } } /// /// Gets the Method collection, or the members that are actually methods. /// public PSMemberInfoCollection Methods { get { return _methods; } } #region virtual implementation /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { if (_constructorPSObject == null) { PSMemberSet memberSet = new PSMemberSet(name); foreach (PSMemberInfo member in this.Members) { memberSet.Members.Add(member); } CloneBaseProperties(memberSet); return memberSet; } else { return new PSMemberSet(name, _constructorPSObject); } } /// /// Gets the member type. For PSMemberSet the member type is PSMemberTypes.MemberSet. /// public override PSMemberTypes MemberType { get { return PSMemberTypes.MemberSet; } } /// /// Gets the value of this member. The getter returns the PSMemberSet itself. /// /// When trying to set the property public override object Value { get { return this; } set { throw new ExtendedTypeSystemException("CannotChangePSMemberSetValue", null, ExtendedTypeSystem.CannotSetValueForMemberType, this.GetType().FullName); } } /// /// Gets the type of the value for this member. This returns typeof(PSMemberSet).FullName. /// public override string TypeNameOfValue { get { return typeof(PSMemberSet).FullName; } } #endregion virtual implementation } /// /// This MemberSet is used internally to represent the memberset for properties /// PSObject, PSBase, PSAdapted members of a PSObject. Having a specialized /// memberset enables delay loading the members for these members. This saves /// time loading the members of a PSObject. /// /// /// This is added to improve hosting PowerShell's PSObjects in a ASP.Net GridView /// Control /// internal class PSInternalMemberSet : PSMemberSet { private object _syncObject = new Object(); private PSObject _psObject; #region Constructor /// /// Constructs the specialized member set. /// /// /// Should be one of PSObject, PSBase, PSAdapted /// /// /// original PSObject to use to generate members /// internal PSInternalMemberSet(string propertyName, PSObject psObject) : base(propertyName) { this.internalMembers = null; _psObject = psObject; } #endregion #region virtual overrides /// /// Generates the members when needed. /// internal override PSMemberInfoInternalCollection InternalMembers { get { // do not cache "psadapted" if (name.Equals(PSObject.AdaptedMemberSetName, StringComparison.OrdinalIgnoreCase)) { return GetInternalMembersFromAdapted(); } // cache "psbase" and "psobject" if (null == internalMembers) { lock (_syncObject) { if (null == internalMembers) { internalMembers = new PSMemberInfoInternalCollection(); switch (name.ToLowerInvariant()) { case PSObject.BaseObjectMemberSetName: GenerateInternalMembersFromBase(); break; case PSObject.PSObjectMemberSetName: GenerateInternalMembersFromPSObject(); break; default: Diagnostics.Assert(false, string.Format(CultureInfo.InvariantCulture, "PSInternalMemberSet cannot process {0}", name)); break; } } } } return internalMembers; } } #endregion #region Private Methods private void GenerateInternalMembersFromBase() { if (_psObject.isDeserialized) { if (_psObject.clrMembers != null) { foreach (PSMemberInfo member in _psObject.clrMembers) { internalMembers.Add(member.Copy()); } } } else { foreach (PSMemberInfo member in PSObject.dotNetInstanceAdapter.BaseGetMembers(_psObject.ImmediateBaseObject)) { internalMembers.Add(member.Copy()); } } } private PSMemberInfoInternalCollection GetInternalMembersFromAdapted() { PSMemberInfoInternalCollection retVal = new PSMemberInfoInternalCollection(); if (_psObject.isDeserialized) { if (_psObject.adaptedMembers != null) { foreach (PSMemberInfo member in _psObject.adaptedMembers) { retVal.Add(member.Copy()); } } } else { foreach (PSMemberInfo member in _psObject.InternalAdapter.BaseGetMembers( _psObject.ImmediateBaseObject)) { retVal.Add(member.Copy()); } } return retVal; } private void GenerateInternalMembersFromPSObject() { PSMemberInfoCollection members = PSObject.dotNetInstanceAdapter.BaseGetMembers( _psObject); foreach (PSMemberInfo member in members) { internalMembers.Add(member.Copy()); } } #endregion } /// /// Serves as a list of property names /// /// /// It is permitted to subclass /// but there is no established scenario for doing this, nor has it been tested. /// public class PSPropertySet : PSMemberInfo { /// /// Returns the string representation of this member /// /// This property as a string public override string ToString() { StringBuilder returnValue = new StringBuilder(); returnValue.Append(this.Name); returnValue.Append(" {"); if (ReferencedPropertyNames.Count != 0) { foreach (string property in ReferencedPropertyNames) { returnValue.Append(property); returnValue.Append(", "); } returnValue.Remove(returnValue.Length - 2, 2); } returnValue.Append("}"); return returnValue.ToString(); } /// /// Initializes a new instance of PSPropertySet with a name and list of property names /// /// name of the set /// name of the properties in the set /// for invalid arguments public PSPropertySet(string name, IEnumerable referencedPropertyNames) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } this.name = name; if (referencedPropertyNames == null) { throw PSTraceSource.NewArgumentNullException("referencedPropertyNames"); } ReferencedPropertyNames = new Collection(); foreach (string referencedPropertyName in referencedPropertyNames) { if (String.IsNullOrEmpty(referencedPropertyName)) { throw PSTraceSource.NewArgumentException("referencedPropertyNames"); } ReferencedPropertyNames.Add(referencedPropertyName); } } /// /// Gets the property names in this property set /// public Collection ReferencedPropertyNames { get; } #region virtual implementation /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { PSPropertySet member = new PSPropertySet(name, ReferencedPropertyNames); CloneBaseProperties(member); return member; } /// /// Gets the member type /// public override PSMemberTypes MemberType { get { return PSMemberTypes.PropertySet; } } /// /// Gets the PSPropertySet itself. /// /// When setting the member public override object Value { get { return this; } set { throw new ExtendedTypeSystemException("CannotChangePSPropertySetValue", null, ExtendedTypeSystem.CannotSetValueForMemberType, this.GetType().FullName); } } /// /// Gets the type of the value for this member. This returns typeof(PSPropertySet).FullName. /// public override string TypeNameOfValue { get { return typeof(PSPropertySet).FullName; } } #endregion virtual implementation } /// /// Used to access the adapted or base events from the BaseObject /// /// /// It is permitted to subclass /// but there is no established scenario for doing this, nor has it been tested. /// public class PSEvent : PSMemberInfo { /// /// Returns the string representation of this member /// /// This property as a string public override string ToString() { StringBuilder eventDefinition = new StringBuilder(); eventDefinition.Append(this.baseEvent.ToString()); eventDefinition.Append("("); int loopCounter = 0; foreach (ParameterInfo parameter in baseEvent.EventHandlerType.GetMethod("Invoke").GetParameters()) { if (loopCounter > 0) eventDefinition.Append(", "); eventDefinition.Append(parameter.ParameterType.ToString()); loopCounter++; } eventDefinition.Append(")"); return eventDefinition.ToString(); } internal EventInfo baseEvent; /// /// Constructs this event /// /// The actual event /// for invalid arguments internal PSEvent(EventInfo baseEvent) { this.baseEvent = baseEvent; this.name = baseEvent.Name; } #region virtual implementation /// /// returns a new PSMemberInfo that is a copy of this PSMemberInfo /// /// a new PSMemberInfo that is a copy of this PSMemberInfo public override PSMemberInfo Copy() { PSEvent member = new PSEvent(this.baseEvent); CloneBaseProperties(member); return member; } /// /// Gets the member type /// public override PSMemberTypes MemberType { get { return PSMemberTypes.Event; } } /// /// Gets the value of this member. The getter returns the /// actual .NET event that this type wraps. /// /// When setting the member public sealed override object Value { get { return baseEvent; } set { throw new ExtendedTypeSystemException("CannotChangePSEventInfoValue", null, ExtendedTypeSystem.CannotSetValueForMemberType, this.GetType().FullName); } } /// /// Gets the type of the value for this member. This always returns typeof(PSMethod).FullName. /// public override string TypeNameOfValue { get { return typeof(PSEvent).FullName; } } #endregion virtual implementation } /// /// A dynamic member /// public class PSDynamicMember : PSMemberInfo { internal PSDynamicMember(string name) { this.name = name; } /// public override string ToString() { return "dynamic " + Name; } /// public override PSMemberTypes MemberType { get { return PSMemberTypes.Dynamic; } } /// public override object Value { get { throw PSTraceSource.NewInvalidOperationException(); } set { throw PSTraceSource.NewInvalidOperationException(); } } /// public override string TypeNameOfValue { get { return "dynamic"; } } /// public override PSMemberInfo Copy() { return new PSDynamicMember(Name); } } #endregion PSMemberInfo #region Member collection classes and its auxilliary classes /// /// /// This class is used in PSMemberInfoInternalCollection and ReadOnlyPSMemberInfoCollection /// internal class MemberMatch { internal static WildcardPattern GetNamePattern(string name) { if (name != null && WildcardPattern.ContainsWildcardCharacters(name)) { return WildcardPattern.Get(name, WildcardOptions.IgnoreCase); } return null; } /// /// Returns all members in memberList matching name and memberTypes /// /// Members to look for member with the correct types and name. /// Name of the members to look for. The name might contain globbing characters /// WildcardPattern out of name /// type of members we want to retrieve /// A collection of members of the right types and name extracted from memberList. /// for invalid arguments internal static PSMemberInfoInternalCollection Match(PSMemberInfoInternalCollection memberList, string name, WildcardPattern nameMatch, PSMemberTypes memberTypes) where T : PSMemberInfo { PSMemberInfoInternalCollection returnValue = new PSMemberInfoInternalCollection(); if (memberList == null) { throw PSTraceSource.NewArgumentNullException("memberList"); } if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } if (nameMatch == null) { T member = memberList[name]; if (member != null && (member.MemberType & memberTypes) != 0) { returnValue.Add(member); } return returnValue; } foreach (T member in memberList) { if (nameMatch.IsMatch(member.Name) && ((member.MemberType & memberTypes) != 0)) { returnValue.Add(member); } } return returnValue; } } /// /// Serves as the collection of members in an PSObject or MemberSet /// public abstract class PSMemberInfoCollection : IEnumerable where T : PSMemberInfo { #region ctor /// /// Initializes a new instance of an PSMemberInfoCollection derived class /// protected PSMemberInfoCollection() { } #endregion ctor #region abstract /// /// Adds a member to this collection /// /// member to be added /// /// When: /// adding a member to an PSMemberSet from the type configuration file or /// adding a member with a reserved member name or /// trying to add a member with a type not compatible with this collection or /// a member by this name is already present /// /// for invalid arguments public abstract void Add(T member); /// /// Adds a member to this collection /// /// member to be added /// flag to indicate that validation has already been done /// on this new member. Use only when you can guarantee that the input will not /// cause any of the errors normally caught by this method. /// /// When: /// adding a member to an PSMemberSet from the type configuration file or /// adding a member with a reserved member name or /// trying to add a member with a type not compatible with this collection or /// a member by this name is already present /// /// for invalid arguments public abstract void Add(T member, bool preValidated); /// /// Removes a member from this collection /// /// name of the member to be removed /// /// When: /// removing a member from an PSMemberSet from the type configuration file /// removing a member with a reserved member name or /// trying to remove a member with a type not compatible with this collection /// /// for invalid arguments public abstract void Remove(string name); /// /// Gets the member in this collection matching name. If the member does not exist, null is returned. /// /// name of the member to look for /// the member matching name /// for invalid arguments public abstract T this[string name] { get; } #endregion abstract #region Match /// /// Returns all members in the collection matching name /// /// name of the members to be return. May contain wildcard characters. /// all members in the collection matching name /// for invalid arguments public abstract ReadOnlyPSMemberInfoCollection Match(string name); /// /// Returns all members in the collection matching name and types /// /// name of the members to be return. May contain wildcard characters. /// type of the members to be searched. /// all members in the collection matching name and types /// for invalid arguments public abstract ReadOnlyPSMemberInfoCollection Match(string name, PSMemberTypes memberTypes); /// /// Returns all members in the collection matching name and types /// /// name of the members to be return. May contain wildcard characters. /// type of the members to be searched. /// match options /// all members in the collection matching name and types /// for invalid arguments internal abstract ReadOnlyPSMemberInfoCollection Match(string name, PSMemberTypes memberTypes, MshMemberMatchOptions matchOptions); #endregion Match internal static bool IsReservedName(string name) { return (String.Equals(name, PSObject.BaseObjectMemberSetName, StringComparison.OrdinalIgnoreCase) || String.Equals(name, PSObject.AdaptedMemberSetName, StringComparison.OrdinalIgnoreCase) || String.Equals(name, PSObject.ExtendedMemberSetName, StringComparison.OrdinalIgnoreCase) || String.Equals(name, PSObject.PSObjectMemberSetName, StringComparison.OrdinalIgnoreCase) || String.Equals(name, PSObject.PSTypeNames, StringComparison.OrdinalIgnoreCase)); } #region IEnumerable /// /// Gets the general enumerator for this collection /// /// the enumerator for this collection IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } /// /// Gets the specific enumerator for this collection. /// /// the enumerator for this collection public abstract IEnumerator GetEnumerator(); #endregion IEnumerable } /// /// Serves as a read only collection of members /// /// /// It is permitted to subclass /// but there is no established scenario for doing this, nor has it been tested. /// public class ReadOnlyPSMemberInfoCollection : IEnumerable where T : PSMemberInfo { private PSMemberInfoInternalCollection _members; /// /// Initializes a new instance of ReadOnlyPSMemberInfoCollection with the given members /// /// /// for invalid arguments internal ReadOnlyPSMemberInfoCollection(PSMemberInfoInternalCollection members) { if (members == null) { throw PSTraceSource.NewArgumentNullException("members"); } _members = members; } /// /// Return the member in this collection matching name. If the member does not exist, null is returned. /// /// name of the member to look for /// the member matching name /// for invalid arguments public T this[string name] { get { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } return _members[name]; } } /// /// Returns all members in the collection matching name /// /// name of the members to be return. May contain wildcard characters. /// all members in the collection matching name /// for invalid arguments public ReadOnlyPSMemberInfoCollection Match(string name) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } return _members.Match(name); } /// /// Returns all members in the collection matching name and types /// /// name of the members to be return. May contain wildcard characters. /// type of the members to be searched. /// all members in the collection matching name and types /// for invalid arguments public ReadOnlyPSMemberInfoCollection Match(string name, PSMemberTypes memberTypes) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } return _members.Match(name, memberTypes); } /// /// Gets the general enumerator for this collection /// /// the enumerator for this collection IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } /// /// Gets the specific enumerator for this collection. /// /// the enumerator for this collection public virtual IEnumerator GetEnumerator() { return _members.GetEnumerator(); } /// /// Gets the number of elements in this collection /// public int Count { get { return _members.Count; } } /// /// Returns the 0 based member identified by index /// /// index of the member to retrieve /// for invalid arguments public T this[int index] { get { return _members[index]; } } } /// /// Collection of members /// internal class PSMemberInfoInternalCollection : PSMemberInfoCollection, IEnumerable where T : PSMemberInfo { private readonly OrderedDictionary _members; private int _countHidden; /// /// Constructs this collection /// internal PSMemberInfoInternalCollection() { _members = new OrderedDictionary(StringComparer.OrdinalIgnoreCase); } private void Replace(T oldMember, T newMember) { _members[newMember.Name] = newMember; if (oldMember.IsHidden) { _countHidden--; } if (newMember.IsHidden) { _countHidden++; } } /// /// Adds a member to the collection by replacing the one with the same name /// /// internal void Replace(T newMember) { Diagnostics.Assert(newMember != null, "called from internal code that checks for new member not null"); lock (_members) { var oldMember = _members[newMember.Name] as T; Diagnostics.Assert(oldMember != null, "internal code checks member already exists"); Replace(oldMember, newMember); } } /// /// Adds a member to this collection /// /// member to be added /// when a member by this name is already present /// for invalid arguments public override void Add(T member) { Add(member, false); } /// /// Adds a member to this collection /// /// member to be added /// flag to indicate that validation has already been done /// on this new member. Use only when you can guarantee that the input will not /// cause any of the errors normally caught by this method. /// when a member by this name is already present /// for invalid arguments public override void Add(T member, bool preValidated) { if (member == null) { throw PSTraceSource.NewArgumentNullException("member"); } lock (_members) { var existingMember = _members[member.Name] as T; if (existingMember != null) { Replace(existingMember, member); } else { _members[member.Name] = member; if (member.IsHidden) { _countHidden++; } } } } /// /// Removes a member from this collection /// /// name of the member to be removed /// When removing a member with a reserved member name /// for invalid arguments public override void Remove(string name) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } if (IsReservedName(name)) { throw new ExtendedTypeSystemException("PSMemberInfoInternalCollectionRemoveReservedName", null, ExtendedTypeSystem.ReservedMemberName, name); } lock (_members) { var member = _members[name] as PSMemberInfo; if (member != null) { if (member.IsHidden) { _countHidden--; } _members.Remove(name); } } } /// /// Returns the member in this collection matching name /// /// name of the member to look for /// the member matching name /// for invalid arguments public override T this[string name] { get { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } lock (_members) { return _members[name] as T; } } } /// /// Returns all members in the collection matching name /// /// name of the members to be return. May contain wildcard characters. /// all members in the collection matching name /// for invalid arguments public override ReadOnlyPSMemberInfoCollection Match(string name) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } return Match(name, PSMemberTypes.All, MshMemberMatchOptions.None); } /// /// Returns all members in the collection matching name and types /// /// name of the members to be return. May contain wildcard characters. /// type of the members to be searched. /// all members in the collection matching name and types /// for invalid arguments public override ReadOnlyPSMemberInfoCollection Match(string name, PSMemberTypes memberTypes) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } return Match(name, memberTypes, MshMemberMatchOptions.None); } /// /// Returns all members in the collection matching name and types /// /// name of the members to be return. May contain wildcard characters. /// type of the members to be searched. /// match options /// all members in the collection matching name and types /// for invalid arguments internal override ReadOnlyPSMemberInfoCollection Match(string name, PSMemberTypes memberTypes, MshMemberMatchOptions matchOptions) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } PSMemberInfoInternalCollection internalMembers = GetInternalMembers(matchOptions); return new ReadOnlyPSMemberInfoCollection(MemberMatch.Match(internalMembers, name, MemberMatch.GetNamePattern(name), memberTypes)); } private PSMemberInfoInternalCollection GetInternalMembers(MshMemberMatchOptions matchOptions) { PSMemberInfoInternalCollection returnValue = new PSMemberInfoInternalCollection(); lock (_members) { foreach (T member in _members.Values.OfType()) { if (member.MatchesOptions(matchOptions)) { returnValue.Add(member); } } } return returnValue; } /// /// The number of elements in this collection /// internal int Count { get { lock (_members) { return _members.Count; } } } /// /// The number of elements in this collection not marked as Hidden /// internal int VisibleCount { get { lock (_members) { return _members.Count - _countHidden; } } } /// /// Returns the 0 based member identified by index /// /// index of the member to retrieve /// for invalid arguments internal T this[int index] { get { lock (_members) { return _members[index] as T; } } } /// /// Gets the specific enumerator for this collection. /// This virtual works around the difficulty of implementing /// interfaces virtually. /// /// the enumerator for this collection public override IEnumerator GetEnumerator() { lock (_members) { // Copy the members to a list so that iteration can be performed without holding a lock. return _members.Values.OfType().ToList().GetEnumerator(); } } } #region CollectionEntry internal class CollectionEntry where T : PSMemberInfo { internal delegate PSMemberInfoInternalCollection GetMembersDelegate(PSObject obj); internal delegate T GetMemberDelegate(PSObject obj, string name); internal CollectionEntry(GetMembersDelegate getMembers, GetMemberDelegate getMember, bool shouldReplicateWhenReturning, bool shouldCloneWhenReturning, string collectionNameForTracing) { GetMembers = getMembers; GetMember = getMember; ShouldReplicateWhenReturning = shouldReplicateWhenReturning; ShouldCloneWhenReturning = shouldCloneWhenReturning; CollectionNameForTracing = collectionNameForTracing; } internal GetMembersDelegate GetMembers { get; } internal GetMemberDelegate GetMember { get; } internal bool ShouldReplicateWhenReturning { get; } internal bool ShouldCloneWhenReturning { get; } internal string CollectionNameForTracing { get; } } #endregion CollectionEntry internal static class ReservedNameMembers { private static object GenerateMemberSet(string name, object obj) { PSObject mshOwner = PSObject.AsPSObject(obj); var memberSet = mshOwner.InstanceMembers[name]; if (memberSet == null) { memberSet = new PSInternalMemberSet(name, mshOwner) { ShouldSerialize = false, IsHidden = true, IsReservedMember = true }; mshOwner.InstanceMembers.Add(memberSet); memberSet.instance = mshOwner; } return memberSet; } internal static object GeneratePSBaseMemberSet(object obj) { return GenerateMemberSet(PSObject.BaseObjectMemberSetName, obj); } internal static object GeneratePSAdaptedMemberSet(object obj) { return GenerateMemberSet(PSObject.AdaptedMemberSetName, obj); } internal static object GeneratePSObjectMemberSet(object obj) { return GenerateMemberSet(PSObject.PSObjectMemberSetName, obj); } internal static object GeneratePSExtendedMemberSet(object obj) { PSObject mshOwner = PSObject.AsPSObject(obj); var memberSet = mshOwner.InstanceMembers[PSObject.ExtendedMemberSetName]; if (memberSet == null) { memberSet = new PSMemberSet(PSObject.ExtendedMemberSetName, mshOwner) { ShouldSerialize = false, IsHidden = true, IsReservedMember = true }; memberSet.ReplicateInstance(mshOwner); memberSet.instance = mshOwner; mshOwner.InstanceMembers.Add(memberSet); } return memberSet; } // This is the implementation of the PSTypeNames CodeProperty. public static Collection PSTypeNames(PSObject o) { return o.TypeNames; } internal static void GeneratePSTypeNames(object obj) { PSObject mshOwner = PSObject.AsPSObject(obj); if (null != mshOwner.InstanceMembers[PSObject.PSTypeNames]) { // PSTypeNames member set is already generated..just return. return; } PSCodeProperty codeProperty = new PSCodeProperty(PSObject.PSTypeNames, CachedReflectionInfo.ReservedNameMembers_PSTypeNames) { ShouldSerialize = false, instance = mshOwner, IsHidden = true, IsReservedMember = true }; mshOwner.InstanceMembers.Add(codeProperty); } } internal class PSMemberInfoIntegratingCollection : PSMemberInfoCollection, IEnumerable where T : PSMemberInfo { #region reserved names private void GenerateAllReservedMembers() { if (!_mshOwner.hasGeneratedReservedMembers) { _mshOwner.hasGeneratedReservedMembers = true; ReservedNameMembers.GeneratePSExtendedMemberSet(_mshOwner); ReservedNameMembers.GeneratePSBaseMemberSet(_mshOwner); ReservedNameMembers.GeneratePSObjectMemberSet(_mshOwner); ReservedNameMembers.GeneratePSAdaptedMemberSet(_mshOwner); ReservedNameMembers.GeneratePSTypeNames(_mshOwner); } } #endregion reserved names #region Constructor, fields and properties internal Collection> Collections { get; } private PSObject _mshOwner; private PSMemberSet _memberSetOwner; internal PSMemberInfoIntegratingCollection(object owner, Collection> collections) { if (owner == null) { throw PSTraceSource.NewArgumentNullException("owner"); } _mshOwner = owner as PSObject; _memberSetOwner = owner as PSMemberSet; if (_mshOwner == null && _memberSetOwner == null) { throw PSTraceSource.NewArgumentException("owner"); } if (collections == null) { throw PSTraceSource.NewArgumentNullException("collections"); } Collections = collections; } #endregion Constructor, fields and properties #region overrides /// /// Adds member to the collection /// /// member to be added /// /// When /// member is an PSProperty or PSMethod /// adding a member to a MemberSet with a reserved name /// adding a member with a reserved member name or /// adding a member with a type not compatible with this collection /// a member with this name already exists /// trying to add a member to a static memberset /// /// for invalid arguments public override void Add(T member) { Add(member, false); } /// /// Adds member to the collection /// /// member to be added /// flag to indicate that validation has already been done /// on this new member. Use only when you can guarantee that the input will not /// cause any of the errors normally caught by this method. /// /// When /// member is an PSProperty or PSMethod /// adding a member to a MemberSet with a reserved name /// adding a member with a reserved member name or /// adding a member with a type not compatible with this collection /// a member with this name already exists /// trying to add a member to a static memberset /// /// for invalid arguments public override void Add(T member, bool preValidated) { if (member == null) { throw PSTraceSource.NewArgumentNullException("member"); } if (!preValidated) { if (member.MemberType == PSMemberTypes.Property || member.MemberType == PSMemberTypes.Method) { throw new ExtendedTypeSystemException( "CannotAddMethodOrProperty", null, ExtendedTypeSystem.CannotAddPropertyOrMethod); } if (_memberSetOwner != null && _memberSetOwner.IsReservedMember) { throw new ExtendedTypeSystemException("CannotAddToReservedNameMemberset", null, ExtendedTypeSystem.CannotChangeReservedMember, _memberSetOwner.Name); } } AddToReservedMemberSet(member, preValidated); } /// /// Auxiliary to add members from types.xml /// /// /// internal void AddToReservedMemberSet(T member, bool preValidated) { if (!preValidated) { if (_memberSetOwner != null && !_memberSetOwner.IsInstance) { throw new ExtendedTypeSystemException("RemoveMemberFromStaticMemberSet", null, ExtendedTypeSystem.ChangeStaticMember, member.Name); } } AddToTypesXmlCache(member, preValidated); } /// /// Adds member to the collection /// /// member to be added /// flag to indicate that validation has already been done /// on this new member. Use only when you can guarantee that the input will not /// cause any of the errors normally caught by this method. /// /// When /// adding a member with a reserved member name or /// adding a member with a type not compatible with this collection /// a member with this name already exists /// trying to add a member to a static memberset /// /// for invalid arguments internal void AddToTypesXmlCache(T member, bool preValidated) { if (member == null) { throw PSTraceSource.NewArgumentNullException("member"); } if (!preValidated) { if (IsReservedName(member.Name)) { throw new ExtendedTypeSystemException("PSObjectMembersMembersAddReservedName", null, ExtendedTypeSystem.ReservedMemberName, member.Name); } } PSMemberInfo memberToBeAdded = member.Copy(); if (_mshOwner != null) { if (!preValidated) { TypeTable typeTable = _mshOwner.GetTypeTable(); if (typeTable != null) { PSMemberInfoInternalCollection typesXmlMembers = typeTable.GetMembers(_mshOwner.InternalTypeNames); if (typesXmlMembers[member.Name] != null) { throw new ExtendedTypeSystemException( "AlreadyPresentInTypesXml", null, ExtendedTypeSystem.MemberAlreadyPresentFromTypesXml, member.Name); } } } memberToBeAdded.ReplicateInstance(_mshOwner); _mshOwner.InstanceMembers.Add(memberToBeAdded, preValidated); // All member binders may need to invalidate dynamic sites, and now must generate // different binding restrictions (specifically, must check for an instance member // before considering the type table or adapted members.) PSGetMemberBinder.SetHasInstanceMember(memberToBeAdded.Name); PSVariableAssignmentBinder.NoteTypeHasInstanceMemberOrTypeName(PSObject.Base(_mshOwner).GetType()); return; } _memberSetOwner.InternalMembers.Add(memberToBeAdded, preValidated); } /// /// Removes the member named name from the collection /// /// Name of the member to be removed /// /// When trying to remove a member with a type not compatible with this collection /// When trying to remove a member from a static memberset /// When trying to remove a member from a MemberSet with a reserved name /// /// for invalid arguments public override void Remove(string name) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } if (_mshOwner != null) { _mshOwner.InstanceMembers.Remove(name); return; } if (!_memberSetOwner.IsInstance) { throw new ExtendedTypeSystemException("AddMemberToStaticMemberSet", null, ExtendedTypeSystem.ChangeStaticMember, name); } if (IsReservedName(_memberSetOwner.Name)) { throw new ExtendedTypeSystemException("CannotRemoveFromReservedNameMemberset", null, ExtendedTypeSystem.CannotChangeReservedMember, _memberSetOwner.Name); } _memberSetOwner.InternalMembers.Remove(name); } /// /// Method which checks if the is reserved and if so /// it will ensure that the particular reserved member is loaded into the /// objects member collection. /// /// Caller should ensure that name is not null or empty. /// /// /// Name of the member to check and load (if needed). /// private void EnsureReservedMemberIsLoaded(string name) { Diagnostics.Assert(!String.IsNullOrEmpty(name), "Name cannot be null or empty"); // Length >= psbase (shortest special member) if (name.Length >= 6 && (name[0] == 'p' || name[0] == 'P') && (name[1] == 's' || name[1] == 'S')) { switch (name.ToLowerInvariant()) { case PSObject.BaseObjectMemberSetName: ReservedNameMembers.GeneratePSBaseMemberSet(_mshOwner); break; case PSObject.AdaptedMemberSetName: ReservedNameMembers.GeneratePSAdaptedMemberSet(_mshOwner); break; case PSObject.ExtendedMemberSetName: ReservedNameMembers.GeneratePSExtendedMemberSet(_mshOwner); break; case PSObject.PSObjectMemberSetName: ReservedNameMembers.GeneratePSObjectMemberSet(_mshOwner); break; case PSObject.PSTypeNames: ReservedNameMembers.GeneratePSTypeNames(_mshOwner); break; default: break; } } } /// /// Returns the name corresponding to name or null if it is not present /// /// name of the member to return /// for invalid arguments public override T this[string name] { get { using (PSObject.memberResolution.TraceScope("Lookup")) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } PSMemberInfo member; object delegateOwner; if (_mshOwner != null) { // this will check if name is a reserved name like PSBase, PSTypeNames // if it is a reserved name, ensures the value is loaded. EnsureReservedMemberIsLoaded(name); delegateOwner = _mshOwner; PSMemberInfoInternalCollection instanceMembers; if (PSObject.HasInstanceMembers(_mshOwner, out instanceMembers)) { member = instanceMembers[name]; T memberAsT = member as T; if (memberAsT != null) { PSObject.memberResolution.WriteLine("Found PSObject instance member: {0}.", name); return memberAsT; } } } else { member = _memberSetOwner.InternalMembers[name]; delegateOwner = _memberSetOwner.instance; T memberAsT = member as T; if (memberAsT != null) { // In membersets we cannot replicate the instance when adding // since the memberset might not yet have an associated PSObject. // We replicate the instance when returning the members of the memberset. PSObject.memberResolution.WriteLine("Found PSMemberSet member: {0}.", name); member.ReplicateInstance(delegateOwner); return memberAsT; } } if (delegateOwner == null) return null; delegateOwner = PSObject.AsPSObject(delegateOwner); foreach (CollectionEntry collection in Collections) { Diagnostics.Assert(delegateOwner != null, "all integrating collections with non emtpty collections have an associated PSObject"); T memberAsT = collection.GetMember((PSObject)delegateOwner, name); if (memberAsT != null) { if (collection.ShouldCloneWhenReturning) { memberAsT = (T)memberAsT.Copy(); } if (collection.ShouldReplicateWhenReturning) { memberAsT.ReplicateInstance(delegateOwner); } return memberAsT; } } return null; } } } private PSMemberInfoInternalCollection GetIntegratedMembers(MshMemberMatchOptions matchOptions) { using (PSObject.memberResolution.TraceScope("Generating the total list of members")) { PSMemberInfoInternalCollection returnValue = new PSMemberInfoInternalCollection(); object delegateOwner; if (_mshOwner != null) { delegateOwner = _mshOwner; foreach (PSMemberInfo member in _mshOwner.InstanceMembers) { if (member.MatchesOptions(matchOptions)) { T memberAsT = member as T; if (memberAsT != null) { returnValue.Add(memberAsT); } } } } else { delegateOwner = _memberSetOwner.instance; foreach (PSMemberInfo member in _memberSetOwner.InternalMembers) { if (member.MatchesOptions(matchOptions)) { T memberAsT = member as T; if (memberAsT != null) { member.ReplicateInstance(delegateOwner); returnValue.Add(memberAsT); } } } } if (delegateOwner == null) return returnValue; delegateOwner = PSObject.AsPSObject(delegateOwner); foreach (CollectionEntry collection in Collections) { PSMemberInfoInternalCollection members = collection.GetMembers((PSObject)delegateOwner); foreach (T member in members) { PSMemberInfo previousMember = returnValue[member.Name]; if (previousMember != null) { PSObject.memberResolution.WriteLine("Member \"{0}\" of type \"{1}\" has been ignored because a member with the same name and type \"{2}\" is already present.", member.Name, member.MemberType, previousMember.MemberType); continue; } if (!member.MatchesOptions(matchOptions)) { PSObject.memberResolution.WriteLine("Skipping hidden member \"{0}\".", member.Name); continue; } T memberToAdd; if (collection.ShouldCloneWhenReturning) { memberToAdd = (T)member.Copy(); } else { memberToAdd = member; } if (collection.ShouldReplicateWhenReturning) { memberToAdd.ReplicateInstance(delegateOwner); } returnValue.Add(memberToAdd); } } return returnValue; } } /// /// Returns all members in the collection matching name /// /// name of the members to be return. May contain wildcard characters. /// all members in the collection matching name /// for invalid arguments public override ReadOnlyPSMemberInfoCollection Match(string name) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } return Match(name, PSMemberTypes.All, MshMemberMatchOptions.None); } /// /// Returns all members in the collection matching name and types /// /// name of the members to be return. May contain wildcard characters. /// type of the members to be searched. /// all members in the collection matching name and types /// for invalid arguments public override ReadOnlyPSMemberInfoCollection Match(string name, PSMemberTypes memberTypes) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } return Match(name, memberTypes, MshMemberMatchOptions.None); } /// /// Returns all members in the collection matching name and types /// /// name of the members to be return. May contain wildcard characters. /// type of the members to be searched. /// search options /// all members in the collection matching name and types /// for invalid arguments internal override ReadOnlyPSMemberInfoCollection Match(string name, PSMemberTypes memberTypes, MshMemberMatchOptions matchOptions) { using (PSObject.memberResolution.TraceScope("Matching \"{0}\"", name)) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } if (_mshOwner != null) { GenerateAllReservedMembers(); } WildcardPattern nameMatch = MemberMatch.GetNamePattern(name); PSMemberInfoInternalCollection allMembers = GetIntegratedMembers(matchOptions); ReadOnlyPSMemberInfoCollection returnValue = new ReadOnlyPSMemberInfoCollection(MemberMatch.Match(allMembers, name, nameMatch, memberTypes)); PSObject.memberResolution.WriteLine("{0} total matches.", returnValue.Count); return returnValue; } } /// /// Gets the specific enumerator for this collection. /// This virtual works around the difficulty of implementing /// interfaces virtually. /// /// the enumerator for this collection public override IEnumerator GetEnumerator() { return new Enumerator(this); } #endregion overrides /// /// Enumerable for this class /// internal struct Enumerator : IEnumerator where S : PSMemberInfo { private S _current; private int _currentIndex; private PSMemberInfoInternalCollection _allMembers; /// /// Constructs this instance to enumerate over members /// /// members we are enumerating internal Enumerator(PSMemberInfoIntegratingCollection integratingCollection) { using (PSObject.memberResolution.TraceScope("Enumeration Start")) { _currentIndex = -1; _current = null; _allMembers = integratingCollection.GetIntegratedMembers(MshMemberMatchOptions.None); if (integratingCollection._mshOwner != null) { integratingCollection.GenerateAllReservedMembers(); PSObject.memberResolution.WriteLine("Enumerating PSObject with type \"{0}\".", integratingCollection._mshOwner.ImmediateBaseObject.GetType().FullName); PSObject.memberResolution.WriteLine("PSObject instance members: {0}", _allMembers.VisibleCount); } else { PSObject.memberResolution.WriteLine("Enumerating PSMemberSet \"{0}\".", integratingCollection._memberSetOwner.Name); PSObject.memberResolution.WriteLine("MemberSet instance members: {0}", _allMembers.VisibleCount); } } } /// /// Moves to the next element in the enumeration /// /// /// false if there are no more elements to enumerate /// true otherwise /// public bool MoveNext() { _currentIndex++; S member = null; while (_currentIndex < _allMembers.Count) { member = _allMembers[_currentIndex]; if (!member.IsHidden) { break; } _currentIndex++; } if (_currentIndex < _allMembers.Count) { _current = member; return true; } _current = null; return false; } /// /// Current PSMemberInfo in the enumeration /// /// for invalid arguments S IEnumerator.Current { get { if (_currentIndex == -1) { throw PSTraceSource.NewInvalidOperationException(); } return _current; } } object IEnumerator.Current { get { return ((IEnumerator)this).Current; } } void IEnumerator.Reset() { _currentIndex = -1; _current = null; } /// /// Not supported /// public void Dispose() { } } } #endregion Member collection classes and its auxilliary classes } #pragma warning restore 56503