MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.Collections.ObjectModel;7using System.Collections.Specialized;8using System.ComponentModel;9using System.Diagnostics.CodeAnalysis;10using System.Globalization;11using System.Linq;12using System.Management.Automation.Internal;13using System.Management.Automation.Interpreter;14using System.Management.Automation.Language;15using System.Reflection;16using System.Text;17 18using Microsoft.PowerShell;19using TypeTable = System.Management.Automation.Runspaces.TypeTable;20 21#pragma warning disable 1634, 1691 // Stops compiler from warning about unknown warnings22#pragma warning disable 5650323 24namespace System.Management.Automation25{26 #region PSMemberInfo27 28 /// <summary>29 /// Enumerates all possible types of members.30 /// </summary>31 [TypeConverter(typeof(LanguagePrimitives.EnumMultipleTypeConverter))]32 [Flags]33 public enum PSMemberTypes34 {35 /// <summary>36 /// An alias to another member.37 /// </summary>38 AliasProperty = 1,39 40 /// <summary>41 /// A property defined as a reference to a method.42 /// </summary>43 CodeProperty = 2,44 45 /// <summary>46 /// A property from the BaseObject.47 /// </summary>48 Property = 4,49 50 /// <summary>51 /// A property defined by a Name-Value pair.52 /// </summary>53 NoteProperty = 8,54 55 /// <summary>56 /// A property defined by script language.57 /// </summary>58 ScriptProperty = 16,59 60 /// <summary>61 /// A set of properties.62 /// </summary>63 PropertySet = 32,64 65 /// <summary>66 /// A method from the BaseObject.67 /// </summary>68 Method = 64,69 70 /// <summary>71 /// A method defined as a reference to another method.72 /// </summary>73 CodeMethod = 128,74 75 /// <summary>76 /// A method defined as a script.77 /// </summary>78 ScriptMethod = 256,79 80 /// <summary>81 /// A member that acts like a Property that takes parameters. This is not consider to be a property or a method.82 /// </summary>83 ParameterizedProperty = 512,84 85 /// <summary>86 /// A set of members.87 /// </summary>88 MemberSet = 1024,89 90 /// <summary>91 /// All events.92 /// </summary>93 Event = 2048,94 95 /// <summary>96 /// All dynamic members (where PowerShell cannot know the type of the member)97 /// </summary>98 Dynamic = 4096,99 100 /// <summary>101 /// Members that are inferred by type inference for PSObject and hashtable.102 /// </summary>103 InferredProperty = 8192,104 /// <summary>105 /// All property member types.106 /// </summary>107 Properties = AliasProperty | CodeProperty | Property | NoteProperty | ScriptProperty | InferredProperty,108 109 /// <summary>110 /// All method member types.111 /// </summary>112 Methods = CodeMethod | Method | ScriptMethod,113 114 /// <summary>115 /// All member types.116 /// </summary>117 All = Properties | Methods | Event | PropertySet | MemberSet | ParameterizedProperty | Dynamic118 }119 120 /// <summary>121 /// Enumerator for all possible views available on a PSObject.122 /// </summary>123 [TypeConverter(typeof(LanguagePrimitives.EnumMultipleTypeConverter))]124 [Flags]125 public enum PSMemberViewTypes126 {127 /// <summary>128 /// Extended methods / properties.129 /// </summary>130 Extended = 1,131 132 /// <summary>133 /// Adapted methods / properties.134 /// </summary>135 Adapted = 2,136 137 /// <summary>138 /// Base methods / properties.139 /// </summary>140 Base = 4,141 142 /// <summary>143 /// All methods / properties.144 /// </summary>145 All = Extended | Adapted | Base146 }147 148 /// <summary>149 /// Match options.150 /// </summary>151 [Flags]152 internal enum MshMemberMatchOptions153 {154 /// <summary>155 /// No options.156 /// </summary>157 None = 0,158 159 /// <summary>160 /// Hidden members should be displayed.161 /// </summary>162 IncludeHidden = 1,163 164 /// <summary>165 /// Only include members with <see cref="PSMemberInfo.ShouldSerialize"/> property set to <see langword="true"/>166 /// </summary>167 OnlySerializable = 2168 }169 170 /// <summary>171 /// Serves as the base class for all members of an PSObject.172 /// </summary>173 public abstract class PSMemberInfo174 {175 internal object instance;176 internal string name;177 178 internal bool ShouldSerialize { get; set; }179 180 internal virtual void ReplicateInstance(object particularInstance)181 {182 this.instance = particularInstance;183 }184 185 internal void SetValueNoConversion(object setValue)186 {187 if (this is not PSProperty thisAsProperty)188 {189 this.Value = setValue;190 return;191 }192 193 thisAsProperty.SetAdaptedValue(setValue, false);194 }195 196 /// <summary>197 /// Initializes a new instance of an PSMemberInfo derived class.198 /// </summary>199 protected PSMemberInfo()200 {201 ShouldSerialize = true;202 IsInstance = true;203 }204 205 internal void CloneBaseProperties(PSMemberInfo destiny)206 {207 destiny.name = name;208 destiny.IsHidden = IsHidden;209 destiny.IsReservedMember = IsReservedMember;210 destiny.IsInstance = IsInstance;211 destiny.instance = instance;212 destiny.ShouldSerialize = ShouldSerialize;213 }214 215 /// <summary>216 /// Gets the member type.217 /// </summary>218 public abstract PSMemberTypes MemberType { get; }219 220 /// <summary>221 /// Gets the member name.222 /// </summary>223 public string Name => this.name;224 225 /// <summary>226 /// Allows a derived class to set the member name...227 /// </summary>228 /// <param name="name"></param>229 protected void SetMemberName(string name)230 {231 if (string.IsNullOrEmpty(name))232 {233 throw PSTraceSource.NewArgumentException(nameof(name));234 }235 236 this.name = name;237 }238 239 /// <summary>240 /// True if this is one of the reserved members.241 /// </summary>242 internal bool IsReservedMember { get; set; }243 244 /// <summary>245 /// True if the member should be hidden when searching with PSMemberInfoInternalCollection's Match246 /// or enumerating a collection.247 /// This should not be settable as it would make the count of hidden properties in248 /// PSMemberInfoInternalCollection invalid.249 /// For now, we are carefully setting this.isHidden before adding250 /// the members toPSObjectMembersetCollection. In the future, we might need overload for all251 /// PSMemberInfo constructors to take isHidden.252 /// </summary>253 internal bool IsHidden { get; set; }254 255 /// <summary>256 /// True if this member has been added to the instance as opposed to257 /// coming from the adapter or from type data.258 /// </summary>259 public bool IsInstance { get; internal set; }260 261 /// <summary>262 /// Gets and Sets the value of this member.263 /// </summary>264 /// <exception cref="GetValueException">When getting the value of a property throws an exception.265 /// This exception is also thrown if the property is an <see cref="PSScriptProperty"/> and there266 /// is no Runspace to run the script.</exception>267 /// <exception cref="SetValueException">When setting the value of a property throws an exception.268 /// This exception is also thrown if the property is an <see cref="PSScriptProperty"/> and there269 /// is no Runspace to run the script.</exception>270 /// <exception cref="ExtendedTypeSystemException">When some problem other then getting/setting the value happened.</exception>271 public abstract object Value { get; set; }272 273 /// <summary>274 /// Gets the type of the value for this member.275 /// </summary>276 /// <exception cref="ExtendedTypeSystemException">When there was a problem getting the property.</exception>277 public abstract string TypeNameOfValue { get; }278 279 /// <summary>280 /// Returns a new PSMemberInfo that is a copy of this PSMemberInfo.281 /// </summary>282 /// <returns>A new PSMemberInfo that is a copy of this PSMemberInfo.</returns>283 public abstract PSMemberInfo Copy();284 285 internal bool MatchesOptions(MshMemberMatchOptions options)286 {287 if (this.IsHidden && ((options & MshMemberMatchOptions.IncludeHidden) == 0))288 {289 return false;290 }291 292 if (!this.ShouldSerialize && ((options & MshMemberMatchOptions.OnlySerializable) != 0))293 {294 return false;295 }296 297 return true;298 }299 }300 301 /// <summary>302 /// Serves as a base class for all members that behave like properties.303 /// </summary>304 public abstract class PSPropertyInfo : PSMemberInfo305 {306 /// <summary>307 /// Initializes a new instance of an PSPropertyInfo derived class.308 /// </summary>309 protected PSPropertyInfo()310 {311 }312 313 /// <summary>314 /// Gets true if this property can be set.315 /// </summary>316 public abstract bool IsSettable { get; }317 318 /// <summary>319 /// Gets true if this property can be read.320 /// </summary>321 public abstract bool IsGettable { get; }322 323 internal Exception NewSetValueException(Exception e, string errorId)324 {325 return new SetValueInvocationException(errorId,326 e,327 ExtendedTypeSystem.ExceptionWhenSetting,328 this.Name, e.Message);329 }330 331 internal Exception NewGetValueException(Exception e, string errorId)332 {333 return new GetValueInvocationException(errorId,334 e,335 ExtendedTypeSystem.ExceptionWhenGetting,336 this.Name, e.Message);337 }338 }339 340 /// <summary>341 /// Serves as an alias to another member.342 /// </summary>343 /// <remarks>344 /// It is permitted to subclass <see cref="PSAliasProperty"/>345 /// but there is no established scenario for doing this, nor has it been tested.346 /// </remarks>347 public class PSAliasProperty : PSPropertyInfo348 {349 /// <summary>350 /// Returns the string representation of this property.351 /// </summary>352 /// <returns>This property as a string.</returns>353 public override string ToString()354 {355 StringBuilder returnValue = new StringBuilder();356 returnValue.Append(this.Name);357 returnValue.Append(" = ");358 if (ConversionType != null)359 {360 returnValue.Append('(');361 returnValue.Append(ConversionType);362 returnValue.Append(')');363 }364 365 returnValue.Append(ReferencedMemberName);366 return returnValue.ToString();367 }368 369 /// <summary>370 /// Initializes a new instance of PSAliasProperty setting the name of the alias371 /// and the name of the member this alias refers to.372 /// </summary>373 /// <param name="name">Name of the alias.</param>374 /// <param name="referencedMemberName">Name of the member this alias refers to.</param>375 /// <exception cref="ArgumentException">For invalid arguments.</exception>376 public PSAliasProperty(string name, string referencedMemberName)377 {378 if (string.IsNullOrEmpty(name))379 {380 throw PSTraceSource.NewArgumentException(nameof(name));381 }382 383 this.name = name;384 if (string.IsNullOrEmpty(referencedMemberName))385 {386 throw PSTraceSource.NewArgumentException(nameof(referencedMemberName));387 }388 389 ReferencedMemberName = referencedMemberName;390 }391 392 /// <summary>393 /// Initializes a new instance of PSAliasProperty setting the name of the alias,394 /// the name of the member this alias refers to and the type to convert the referenced395 /// member's value.396 /// </summary>397 /// <param name="name">Name of the alias.</param>398 /// <param name="referencedMemberName">Name of the member this alias refers to.</param>399 /// <param name="conversionType">The type to convert the referenced member's value.</param>400 /// <exception cref="ArgumentException">For invalid arguments.</exception>401 public PSAliasProperty(string name, string referencedMemberName, Type conversionType)402 {403 if (string.IsNullOrEmpty(name))404 {405 throw PSTraceSource.NewArgumentException(nameof(name));406 }407 408 this.name = name;409 if (string.IsNullOrEmpty(referencedMemberName))410 {411 throw PSTraceSource.NewArgumentException(nameof(referencedMemberName));412 }413 414 ReferencedMemberName = referencedMemberName;415 // conversionType is optional and can be null416 ConversionType = conversionType;417 }418 419 /// <summary>420 /// Gets the name of the member this alias refers to.421 /// </summary>422 public string ReferencedMemberName { get; }423 424 /// <summary>425 /// Gets the member this alias refers to.426 /// </summary>427 internal PSMemberInfo ReferencedMember => this.LookupMember(ReferencedMemberName);428 429 /// <summary>430 /// Gets the type to convert the referenced member's value. It might be431 /// null when no conversion is done.432 /// </summary>433 public Type ConversionType { get; private set; }434 435 #region virtual implementation436 437 /// <summary>438 /// Returns a new PSMemberInfo that is a copy of this PSMemberInfo.439 /// </summary>440 /// <returns>A new PSMemberInfo that is a copy of this PSMemberInfo.</returns>441 public override PSMemberInfo Copy()442 {443 PSAliasProperty alias = new PSAliasProperty(name, ReferencedMemberName) { ConversionType = ConversionType };444 CloneBaseProperties(alias);445 return alias;446 }447 448 /// <summary>449 /// Gets the member type.450 /// </summary>451 public override PSMemberTypes MemberType => PSMemberTypes.AliasProperty;452 453 /// <summary>454 /// Gets the type of the value for this member.455 /// </summary>456 /// <exception cref="ExtendedTypeSystemException">457 /// When458 /// the alias has not been added to an PSObject or459 /// the alias has a cycle or460 /// an aliased member is not present461 /// </exception>462 public override string TypeNameOfValue463 {464 get465 {466 if (ConversionType != null)467 {468 return ConversionType.FullName;469 }470 471 return this.ReferencedMember.TypeNameOfValue;472 }473 }474 475 /// <summary>476 /// Gets true if this property can be set.477 /// </summary>478 /// <exception cref="ExtendedTypeSystemException">479 /// When480 /// the alias has not been added to an PSObject or481 /// the alias has a cycle or482 /// an aliased member is not present483 /// </exception>484 public override bool IsSettable485 {486 get487 {488 if (this.ReferencedMember is PSPropertyInfo memberProperty)489 {490 return memberProperty.IsSettable;491 }492 493 return false;494 }495 }496 497 /// <summary>498 /// Gets true if this property can be read.499 /// </summary>500 /// <exception cref="ExtendedTypeSystemException">501 /// When502 /// the alias has not been added to an PSObject or503 /// the alias has a cycle or504 /// an aliased member is not present505 /// </exception>506 public override bool IsGettable507 {508 get509 {510 if (this.ReferencedMember is PSPropertyInfo memberProperty)511 {512 return memberProperty.IsGettable;513 }514 515 return false;516 }517 }518 519 private PSMemberInfo LookupMember(string name)520 {521 LookupMember(name, new HashSet<string>(StringComparer.OrdinalIgnoreCase), out PSMemberInfo returnValue, out bool hasCycle);522 if (hasCycle)523 {524 throw new525 ExtendedTypeSystemException(526 "CycleInAliasLookup",527 null,528 ExtendedTypeSystem.CycleInAlias,529 this.Name);530 }531 532 return returnValue;533 }534 535 private void LookupMember(string name, HashSet<string> visitedAliases, out PSMemberInfo returnedMember, out bool hasCycle)536 {537 returnedMember = null;538 if (this.instance == null)539 {540 throw new ExtendedTypeSystemException("AliasLookupMemberOutsidePSObject",541 null,542 ExtendedTypeSystem.AccessMemberOutsidePSObject,543 name);544 }545 546 PSMemberInfo member = PSObject.AsPSObject(this.instance).Properties[name];547 if (member == null)548 {549 throw new ExtendedTypeSystemException(550 "AliasLookupMemberNotPresent",551 null,552 ExtendedTypeSystem.MemberNotPresent,553 name);554 }555 556 if (member is not PSAliasProperty aliasMember)557 {558 hasCycle = false;559 returnedMember = member;560 return;561 }562 563 if (visitedAliases.Contains(name))564 {565 hasCycle = true;566 return;567 }568 569 visitedAliases.Add(name);570 LookupMember(aliasMember.ReferencedMemberName, visitedAliases, out returnedMember, out hasCycle);571 }572 573 /// <summary>574 /// Gets and Sets the value of this member.575 /// </summary>576 /// <exception cref="ExtendedTypeSystemException">577 /// When578 /// the alias has not been added to an PSObject or579 /// the alias has a cycle or580 /// an aliased member is not present581 /// </exception>582 /// <exception cref="GetValueException">When getting the value of a property throws an exception.</exception>583 /// <exception cref="SetValueException">When setting the value of a property throws an exception.</exception>584 public override object Value585 {586 get587 {588 object returnValue = this.ReferencedMember.Value;589 if (ConversionType != null)590 {591 returnValue = LanguagePrimitives.ConvertTo(returnValue, ConversionType, CultureInfo.InvariantCulture);592 }593 594 return returnValue;595 }596 597 set => this.ReferencedMember.Value = value;598 }599 600 #endregion virtual implementation601 }602 603 /// <summary>604 /// Serves as a property implemented with references to methods for getter and setter.605 /// </summary>606 /// <remarks>607 /// It is permitted to subclass <see cref="PSCodeProperty"/>608 /// but there is no established scenario for doing this, nor has it been tested.609 /// </remarks>610 public class PSCodeProperty : PSPropertyInfo611 {612 /// <summary>613 /// Returns the string representation of this property.614 /// </summary>615 /// <returns>This property as a string.</returns>616 public override string ToString()617 {618 StringBuilder returnValue = new StringBuilder();619 returnValue.Append(this.TypeNameOfValue);620 returnValue.Append(' ');621 returnValue.Append(this.Name);622 returnValue.Append('{');623 if (this.IsGettable)624 {625 returnValue.Append("get=");626 returnValue.Append(GetterCodeReference.Name);627 returnValue.Append(';');628 }629 630 if (this.IsSettable)631 {632 returnValue.Append("set=");633 returnValue.Append(SetterCodeReference.Name);634 returnValue.Append(';');635 }636 637 returnValue.Append('}');638 return returnValue.ToString();639 }640 641 /// <summary>642 /// Called from TypeTableUpdate before SetSetterFromTypeTable is called.643 /// </summary>644 internal void SetGetterFromTypeTable(Type type, string methodName)645 {646 MethodInfo methodAsMember = null;647 648 try649 {650 methodAsMember = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase);651 }652 catch (AmbiguousMatchException)653 {654 // Ignore the AmbiguousMatchException.655 // We will generate error below if we cannot find exactly one match method.656 }657 658 if (methodAsMember == null)659 {660 throw new ExtendedTypeSystemException(661 "GetterFormatFromTypeTable",662 null,663 ExtendedTypeSystem.CodePropertyGetterFormat);664 }665 666 SetGetter(methodAsMember);667 }668 669 /// <summary>670 /// Called from TypeTableUpdate after SetGetterFromTypeTable is called.671 /// </summary>672 internal void SetSetterFromTypeTable(Type type, string methodName)673 {674 MethodInfo methodAsMember = null;675 676 try677 {678 methodAsMember = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase);679 }680 catch (AmbiguousMatchException)681 {682 // Ignore the AmbiguousMatchException.683 // We will generate error below if we cannot find exactly one match method.684 }685 686 if (methodAsMember == null)687 {688 throw new ExtendedTypeSystemException(689 "SetterFormatFromTypeTable",690 null,691 ExtendedTypeSystem.CodePropertySetterFormat);692 }693 694 SetSetter(methodAsMember, GetterCodeReference);695 }696 697 /// <summary>698 /// Used from TypeTable with the internal constructor.699 /// </summary>700 internal void SetGetter(MethodInfo methodForGet)701 {702 if (methodForGet == null)703 {704 GetterCodeReference = null;705 return;706 }707 708 if (!CheckGetterMethodInfo(methodForGet))709 {710 throw new ExtendedTypeSystemException(711 "GetterFormat",712 null,713 ExtendedTypeSystem.CodePropertyGetterFormat);714 }715 716 GetterCodeReference = methodForGet;717 }718 719 internal static bool CheckGetterMethodInfo(MethodInfo methodForGet)720 {721 ParameterInfo[] parameters = methodForGet.GetParameters();722 return methodForGet.IsPublic723 && methodForGet.IsStatic724 && methodForGet.ReturnType != typeof(void)725 && parameters.Length == 1726 && parameters[0].ParameterType == typeof(PSObject);727 }728 729 /// <summary>730 /// Used from TypeTable with the internal constructor.731 /// </summary>732 private void SetSetter(MethodInfo methodForSet, MethodInfo methodForGet)733 {734 if (methodForSet == null)735 {736 if (methodForGet == null)737 {738 throw new ExtendedTypeSystemException(739 "SetterAndGetterNullFormat",740 null,741 ExtendedTypeSystem.CodePropertyGetterAndSetterNull);742 }743 744 SetterCodeReference = null;745 return;746 }747 748 if (!CheckSetterMethodInfo(methodForSet, methodForGet))749 {750 throw new ExtendedTypeSystemException(751 "SetterFormat",752 null,753 ExtendedTypeSystem.CodePropertySetterFormat);754 }755 756 SetterCodeReference = methodForSet;757 }758 759 internal static bool CheckSetterMethodInfo(MethodInfo methodForSet, MethodInfo methodForGet)760 {761 ParameterInfo[] parameters = methodForSet.GetParameters();762 return methodForSet.IsPublic763 && methodForSet.IsStatic764 && methodForSet.ReturnType == typeof(void)765 && parameters.Length == 2766 && parameters[0].ParameterType == typeof(PSObject)767 && (methodForGet == null || methodForGet.ReturnType == parameters[1].ParameterType);768 }769 770 /// <summary>771 /// Used from TypeTable to delay setting getter and setter.772 /// </summary>773 internal PSCodeProperty(string name)774 {775 if (string.IsNullOrEmpty(name))776 {777 throw PSTraceSource.NewArgumentException(nameof(name));778 }779 780 this.name = name;781 }782 783 /// <summary>784 /// Initializes a new instance of the PSCodeProperty class as a read only property.785 /// </summary>786 /// <param name="name">Name of the property.</param>787 /// <param name="getterCodeReference">This should be a public static non void method taking one PSObject parameter.</param>788 /// <exception cref="ArgumentException">If name is null or empty or getterCodeReference is null.</exception>789 /// <exception cref="ExtendedTypeSystemException">If getterCodeReference doesn't have the right format.</exception>790 public PSCodeProperty(string name, MethodInfo getterCodeReference)791 {792 if (string.IsNullOrEmpty(name))793 {794 throw PSTraceSource.NewArgumentException(nameof(name));795 }796 797 this.name = name;798 if (getterCodeReference == null)799 {800 throw PSTraceSource.NewArgumentNullException(nameof(getterCodeReference));801 }802 803 SetGetter(getterCodeReference);804 }805 806 /// <summary>807 /// Initializes a new instance of the PSCodeProperty class. Setter or getter can be null, but both cannot be null.808 /// </summary>809 /// <param name="name">Name of the property.</param>810 /// <param name="getterCodeReference">This should be a public static non void method taking one PSObject parameter.</param>811 /// <param name="setterCodeReference">This should be a public static void method taking 2 parameters, where the first is an PSObject.</param>812 /// <exception cref="ArgumentException">When methodForGet and methodForSet are null.</exception>813 /// <exception cref="ExtendedTypeSystemException">814 /// if:815 /// - getterCodeReference doesn't have the right format,816 /// - setterCodeReference doesn't have the right format,817 /// - both getterCodeReference and setterCodeReference are null.818 /// </exception>819 public PSCodeProperty(string name, MethodInfo getterCodeReference, MethodInfo setterCodeReference)820 {821 if (string.IsNullOrEmpty(name))822 {823 throw PSTraceSource.NewArgumentException(nameof(name));824 }825 826 this.name = name;827 if (getterCodeReference == null && setterCodeReference == null)828 {829 throw PSTraceSource.NewArgumentNullException("getterCodeReference setterCodeReference");830 }831 832 SetGetter(getterCodeReference);833 SetSetter(setterCodeReference, getterCodeReference);834 }835 836 /// <summary>837 /// Gets the method used for the properties' getter. It might be null.838 /// </summary>839 public MethodInfo GetterCodeReference { get; private set; }840 841 /// <summary>842 /// Gets the method used for the properties' setter. It might be null.843 /// </summary>844 public MethodInfo SetterCodeReference { get; private set; }845 846 #region virtual implementation847 848 /// <summary>849 /// Returns a new PSMemberInfo that is a copy of this PSMemberInfo.850 /// </summary>851 /// <returns>A new PSMemberInfo that is a copy of this PSMemberInfo.</returns>852 public override PSMemberInfo Copy()853 {854 PSCodeProperty property = new PSCodeProperty(name, GetterCodeReference, SetterCodeReference);855 CloneBaseProperties(property);856 return property;857 }858 859 /// <summary>860 /// Gets the member type.861 /// </summary>862 public override PSMemberTypes MemberType => PSMemberTypes.CodeProperty;863 864 /// <summary>865 /// Gets true if this property can be set.866 /// </summary>867 public override bool IsSettable => this.SetterCodeReference != null;868 869 /// <summary>870 /// Gets true if this property can be read.871 /// </summary>872 public override bool IsGettable => GetterCodeReference != null;873 874 /// <summary>875 /// Gets and Sets the value of this member.876 /// </summary>877 /// <exception cref="GetValueException">When getting and there is no getter or when the getter throws an exception.</exception>878 /// <exception cref="SetValueException">When setting and there is no setter or when the setter throws an exception.</exception>879 [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations", Justification = "<Pending>")]880 public override object Value881 {882 get883 {884 if (GetterCodeReference == null)885 {886 throw new GetValueException(887 "GetWithoutGetterFromCodePropertyValue",888 null,889 ExtendedTypeSystem.GetWithoutGetterException,890 this.Name);891 }892 893 try894 {895 return GetterCodeReference.Invoke(null, new object[] { this.instance });896 }897 catch (TargetInvocationException ex)898 {899 Exception inner = ex.InnerException ?? ex;900 throw new GetValueInvocationException(901 "CatchFromCodePropertyGetTI",902 inner,903 ExtendedTypeSystem.ExceptionWhenGetting,904 this.name,905 inner.Message);906 }907 catch (Exception e)908 {909 if (e is GetValueException)910 {911 throw;912 }913 914 throw new GetValueInvocationException(915 "CatchFromCodePropertyGet",916 e,917 ExtendedTypeSystem.ExceptionWhenGetting,918 this.name,919 e.Message);920 }921 }922 923 set924 {925 if (SetterCodeReference == null)926 {927 throw new SetValueException(928 "SetWithoutSetterFromCodeProperty",929 null,930 ExtendedTypeSystem.SetWithoutSetterException,931 this.Name);932 }933 934 try935 {936 SetterCodeReference.Invoke(null, new object[] { this.instance, value });937 }938 catch (TargetInvocationException ex)939 {940 Exception inner = ex.InnerException ?? ex;941 throw new SetValueInvocationException(942 "CatchFromCodePropertySetTI",943 inner,944 ExtendedTypeSystem.ExceptionWhenSetting,945 this.name,946 inner.Message);947 }948 catch (Exception e)949 {950 if (e is SetValueException)951 {952 throw;953 }954 955 throw new SetValueInvocationException(956 "CatchFromCodePropertySet",957 e,958 ExtendedTypeSystem.ExceptionWhenSetting,959 this.name,960 e.Message);961 }962 }963 }964 965 /// <summary>966 /// Gets the type of the value for this member.967 /// </summary>968 /// <exception cref="GetValueException">If there is no property getter.</exception>969 [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations", Justification = "<Pending>")]970 public override string TypeNameOfValue971 {972 get973 {974 if (GetterCodeReference == null)975 {976 throw new GetValueException(977 "GetWithoutGetterFromCodePropertyTypeOfValue",978 null,979 ExtendedTypeSystem.GetWithoutGetterException,980 this.Name);981 }982 983 return GetterCodeReference.ReturnType.FullName;984 }985 }986 987 #endregion virtual implementation988 }989 990 /// <summary>991 /// Type used to capture the properties inferred from Hashtable and PSObject.992 /// </summary>993 internal class PSInferredProperty : PSPropertyInfo994 {995 public PSInferredProperty(string name, PSTypeName typeName)996 {997 this.name = name;998 TypeName = typeName;999 }1000 1001 internal PSTypeName TypeName { get; }1002 1003 public override PSMemberTypes MemberType => PSMemberTypes.InferredProperty;1004 1005 public override object Value { get; set; }1006 1007 public override string TypeNameOfValue => TypeName.Name;1008 1009 public override PSMemberInfo Copy() => new PSInferredProperty(Name, TypeName);1010 1011 public override bool IsSettable => false;1012 1013 public override bool IsGettable => false;1014 1015 public override string ToString() => $"{ToStringCodeMethods.Type(TypeName.Type)} {Name}";1016 }1017 1018 /// <summary>1019 /// Used to access the adapted or base properties from the BaseObject.1020 /// </summary>1021 public class PSProperty : PSPropertyInfo1022 {1023 /// <summary>1024 /// Returns the string representation of this property.1025 /// </summary>1026 /// <returns>This property as a string.</returns>1027 public override string ToString()1028 {1029 if (this.isDeserialized)1030 {1031 StringBuilder returnValue = new StringBuilder();1032 returnValue.Append(this.TypeNameOfValue);1033 returnValue.Append(" {get;set;}");1034 return returnValue.ToString();1035 }1036 1037 Diagnostics.Assert((this.baseObject != null) && (this.adapter != null), "if it is deserialized, it should have all these properties set");1038 return adapter.BasePropertyToString(this);1039 }1040 1041 /// <summary>1042 /// Used by the adapters to keep intermediate data used between DoGetProperty and1043 /// DoGetValue or DoSetValue.1044 /// </summary>1045 internal string typeOfValue;1046 1047 internal object serializedValue;1048 internal bool isDeserialized;1049 1050 /// <summary>1051 /// This will be either instance.adapter or instance.clrAdapter.1052 /// </summary>1053 internal Adapter adapter;1054 1055 internal object adapterData;1056 internal object baseObject;1057 1058 /// <summary>1059 /// Constructs a property from a serialized value.1060 /// </summary>1061 /// <param name="name">Name of the property.</param>1062 /// <param name="serializedValue">Value of the property.</param>1063 internal PSProperty(string name, object serializedValue)1064 {1065 this.isDeserialized = true;1066 this.serializedValue = serializedValue;1067 this.name = name;1068 }1069 1070 /// <summary>1071 /// Constructs this property.1072 /// </summary>1073 /// <param name="name">Name of the property.</param>1074 /// <param name="adapter">Adapter used in DoGetProperty.</param>1075 /// <param name="baseObject">Object passed to DoGetProperty.</param>1076 /// <param name="adapterData">Adapter specific data.</param>1077 /// <exception cref="ArgumentException">For invalid arguments.</exception>1078 internal PSProperty(string name, Adapter adapter, object baseObject, object adapterData)1079 {1080 if (string.IsNullOrEmpty(name))1081 {1082 throw PSTraceSource.NewArgumentException(nameof(name));1083 }1084 1085 this.name = name;1086 this.adapter = adapter;1087 this.adapterData = adapterData;1088 this.baseObject = baseObject;1089 }1090 1091 #region virtual implementation1092 1093 /// <summary>1094 /// Returns a new PSMemberInfo that is a copy of this PSMemberInfo.1095 /// </summary>1096 /// <returns>A new PSMemberInfo that is a copy of this PSMemberInfo.</returns>1097 public override PSMemberInfo Copy()1098 {1099 PSProperty property = new PSProperty(this.name, this.adapter, this.baseObject, this.adapterData);1100 CloneBaseProperties(property);1101 property.typeOfValue = this.typeOfValue;1102 property.serializedValue = this.serializedValue;1103 property.isDeserialized = this.isDeserialized;1104 return property;1105 }1106 1107 /// <summary>1108 /// Gets the member type.1109 /// </summary>1110 public override PSMemberTypes MemberType => PSMemberTypes.Property;1111 1112 private object GetAdaptedValue()1113 {1114 if (this.isDeserialized)1115 {1116 return serializedValue;1117 }1118 1119 Diagnostics.Assert((this.baseObject != null) && (this.adapter != null), "if it is deserialized, it should have all these properties set");1120 1121 object o = adapter.BasePropertyGet(this);1122 return o;1123 }1124 1125 internal void SetAdaptedValue(object setValue, bool shouldConvert)1126 {1127 if (this.isDeserialized)1128 {1129 serializedValue = setValue;1130 return;1131 }1132 1133 Diagnostics.Assert((this.baseObject != null) && (this.adapter != null), "if it is deserialized, it should have all these properties set");1134 adapter.BasePropertySet(this, setValue, shouldConvert);1135 }1136 1137 /// <summary>1138 /// Gets or sets the value of this property.1139 /// </summary>1140 /// <exception cref="GetValueException">When getting the value of a property throws an exception.</exception>1141 /// <exception cref="SetValueException">When setting the value of a property throws an exception.</exception>1142 public override object Value1143 {1144 get => GetAdaptedValue();1145 set => SetAdaptedValue(value, true);1146 }1147 1148 /// <summary>1149 /// Gets true if this property can be set.1150 /// </summary>1151 public override bool IsSettable1152 {1153 get1154 {1155 if (this.isDeserialized)1156 {1157 return true;1158 }1159 1160 Diagnostics.Assert((this.baseObject != null) && (this.adapter != null), "if it is deserialized, it should have all these properties set");1161 return adapter.BasePropertyIsSettable(this);1162 }1163 }1164 1165 /// <summary>1166 /// Gets true if this property can be read.1167 /// </summary>1168 public override bool IsGettable1169 {1170 get1171 {1172 if (this.isDeserialized)1173 {1174 return true;1175 }1176 1177 Diagnostics.Assert((this.baseObject != null) && (this.adapter != null), "if it is deserialized, it should have all these properties set");1178 return adapter.BasePropertyIsGettable(this);1179 }1180 }1181 1182 /// <summary>1183 /// Gets the type of the value for this member.1184 /// </summary>1185 public override string TypeNameOfValue1186 {1187 get1188 {1189 if (this.isDeserialized)1190 {1191 if (serializedValue == null)1192 {1193 return string.Empty;1194 }1195 1196 if (serializedValue is PSObject serializedValueAsPSObject)1197 {1198 var typeNames = serializedValueAsPSObject.InternalTypeNames;1199 if ((typeNames != null) && (typeNames.Count >= 1))1200 {