Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
TypeResolver.cs981 linesDownload Raw Back to parser
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Concurrent;6using System.Collections.Generic;7using System.Collections.Specialized;8#if !UNIX9using System.DirectoryServices;10#endif11using System.Globalization;12using System.Linq;13using System.Management.Automation.Language;14using System.Management.Automation.Runspaces;15using System.Net;16using System.Net.Mail;17using System.Net.NetworkInformation;18using System.Numerics;19using System.Reflection;20using System.Security;21using System.Security.AccessControl;22using System.Security.Cryptography.X509Certificates;23using System.Text.RegularExpressions;24using System.Xml;25 26using Microsoft.Management.Infrastructure;27using Microsoft.PowerShell.Commands;28 29namespace System.Management.Automation.Language30{31    internal static class TypeResolver32    {33        // our interface34        //    internal static Type ConvertTypeNameToType(TypeName typeName, out Exception exception)35        //        Used by TypeName.GetReflectionType and in TypeResolver36        //    internal static bool TryResolveType(string typeName, out Type type)37        //        Used in a bunch of places38        //    internal static Type ConvertStringToType(string typeName, out Exception exception)39        //        Used primarily in LanguagePrimitives.ConvertTo40 41        private static Type LookForTypeInSingleAssembly(Assembly assembly, string typename)42        {43            Type targetType = assembly.GetType(typename, false, true);44            if (targetType != null && IsPublic(targetType))45            {46                return targetType;47            }48 49            return null;50        }51 52        /// <summary>53        /// Inherited from InvalidCastException, because it happens in [string] -> [Type] conversion.54        /// </summary>55        internal class AmbiguousTypeException : InvalidCastException56        {57            public string[] Candidates { get; }58 59            public TypeName TypeName { get; }60 61            public AmbiguousTypeException(TypeName typeName, IEnumerable<string> candidates)62            {63                Candidates = candidates.ToArray();64                TypeName = typeName;65                Diagnostics.Assert(Candidates.Length > 1, "AmbiguousTypeException can be created only when there are more then 1 candidate.");66            }67        }68 69        private static Type LookForTypeInAssemblies(TypeName typeName,70                                                    IEnumerable<Assembly> assemblies,71                                                    HashSet<Assembly> searchedAssemblies,72                                                    TypeResolutionState typeResolutionState,73                                                    bool reportAmbiguousException,74                                                    out Exception exception)75        {76            exception = null;77            string alternateNameToFind = typeResolutionState.GetAlternateTypeName(typeName.Name);78            Type foundType = null;79            Type foundType2 = null;80            foreach (Assembly assembly in assemblies)81            {82                // Skip the assemblies that we already searched and found no matching type.83                if (searchedAssemblies.Contains(assembly))84                {85                    continue;86                }87 88                try89                {90                    Type targetType = LookForTypeInSingleAssembly(assembly, typeName.Name);91                    if (targetType == null && alternateNameToFind != null)92                    {93                        targetType = LookForTypeInSingleAssembly(assembly, alternateNameToFind);94                    }95 96                    if (targetType != null)97                    {98                        if (!reportAmbiguousException)99                        {100                            // accelerator for the common case, when we are not interested in ambiguity exception.101                            return targetType;102                        }103 104                        // .NET has forward notation for types, when they declared in one assembly and implemented in another one.105                        // We want to support both scenarios:106                        // 1) When we pass assembly with declared forwarded type (CoreCLR)107                        // 2) When we pass assembly with declared forwarded type and assembly with implemented forwarded type (FullCLR)108                        // In the case (2) we should not report duplicate, hence this check109                        if (foundType != targetType)110                        {111                            if (foundType != null)112                            {113                                foundType2 = targetType;114                                break;115                            }116                            else117                            {118                                foundType = targetType;119                            }120                        }121                    }122                    else123                    {124                        // We didn't find a match from the current assembly, so update the searchedAssemblies set.125                        searchedAssemblies.Add(assembly);126                    }127                }128                catch (Exception) // Assembly.GetType might throw unadvertised exceptions129                {130                }131            }132 133            if (foundType2 != null)134            {135                exception = new AmbiguousTypeException(typeName, new string[] { foundType.AssemblyQualifiedName, foundType2.AssemblyQualifiedName });136                return null;137            }138 139            return foundType;140        }141 142        /// <summary>143        /// A type IsPublic if IsPublic or (IsNestedPublic and is nested in public type(s))144        /// </summary>145        internal static bool IsPublic(Type type)146        {147            if (type.IsPublic)148            {149                return true;150            }151 152            if (!type.IsNestedPublic)153            {154                return false;155            }156 157            while ((type = type.DeclaringType) != null)158            {159                if (!(type.IsPublic || type.IsNestedPublic))160                {161                    return false;162                }163            }164 165            return true;166        }167 168        private static Type ResolveTypeNameWorker(TypeName typeName,169                                                  SessionStateScope currentScope,170                                                  IEnumerable<Assembly> loadedAssemblies,171                                                  HashSet<Assembly> searchedAssemblies,172                                                  TypeResolutionState typeResolutionState,173                                                  bool onlySearchInGivenAssemblies,174                                                  bool reportAmbiguousException,175                                                  out Exception exception)176        {177            Type result;178            exception = null;179 180            if (!onlySearchInGivenAssemblies)181            {182                while (currentScope != null)183                {184                    result = currentScope.LookupType(typeName.Name);185                    if (result != null)186                    {187                        return result;188                    }189 190                    currentScope = currentScope.Parent;191                }192 193                if (TypeAccelerators.builtinTypeAccelerators.TryGetValue(typeName.Name, out result))194                {195                    return result;196                }197            }198 199            result = LookForTypeInAssemblies(typeName, loadedAssemblies, searchedAssemblies, typeResolutionState, reportAmbiguousException, out exception);200            if (exception != null)201            {202                // skip the rest of lookups, if exception reported.203                return result;204            }205 206            if (!onlySearchInGivenAssemblies && result == null)207            {208                lock (TypeAccelerators.userTypeAccelerators)209                {210                    TypeAccelerators.userTypeAccelerators.TryGetValue(typeName.Name, out result);211                }212            }213 214            return result;215        }216 217        /// <summary>218        /// A set of assemblies that we have searched from but found no matching type. By checking this set, we can219        /// avoid searching from some assemblies multiple times.220        /// This set is made thread static, so that type resolution happens on the same thread can reuse the HashSet221        /// without having to create a new HashSet instance every time. This will reduce GC given that type resolution222        /// is a frequent operation in powershell script.223        /// </summary>224        /// <remarks>225        /// This set should be used directly only in the method CallResolveTypeNameWorkerHelper.226        /// </remarks>227        [ThreadStatic]228        private static HashSet<Assembly> t_searchedAssemblies = null;229 230        /// <summary>231        /// A helper method to call ResolveTypeNameWorker in steps.232        /// </summary>233        private static Type CallResolveTypeNameWorkerHelper(TypeName typeName,234                                                            ExecutionContext context,235                                                            IEnumerable<Assembly> assemblies,236                                                            bool isAssembliesExplicitlyPassedIn,237                                                            TypeResolutionState typeResolutionState,238                                                            out Exception exception)239        {240            if (t_searchedAssemblies == null)241            {242                t_searchedAssemblies = new HashSet<Assembly>();243            }244            else245            {246                // Clear the set before starting a full search to make sure we have a clean start.247                t_searchedAssemblies.Clear();248            }249 250            try251            {252                exception = null;253                var currentScope = context?.EngineSessionState.CurrentScope;254                Type result = ResolveTypeNameWorker(typeName, currentScope, typeResolutionState.assemblies, t_searchedAssemblies, typeResolutionState,255                                                    /*onlySearchInGivenAssemblies*/ false, /* reportAmbiguousException */ true, out exception);256                if (exception == null && result == null)257                {258                    if (context != null && !isAssembliesExplicitlyPassedIn)259                    {260                        // If the assemblies to search from is not specified by the caller of 'ResolveTypeNameWithContext',261                        // then we search our assembly cache first, so as to give preference to resolving the type against262                        // assemblies explicitly loaded by powershell, for example, via importing module/snapin.263                        result = ResolveTypeNameWorker(typeName, currentScope, context.AssemblyCache.Values, t_searchedAssemblies, typeResolutionState,264                                                    /*onlySearchInGivenAssemblies*/ true, /* reportAmbiguousException */ false, out exception);265                    }266 267                    if (result == null)268                    {269                        // Search from the assembly list passed in.270                        result = ResolveTypeNameWorker(typeName, currentScope, assemblies, t_searchedAssemblies, typeResolutionState,271                                                    /*onlySearchInGivenAssemblies*/ true, /* reportAmbiguousException */ false, out exception);272                    }273                }274 275                return result;276            }277            finally278            {279                // Clear the set after a full search, so dynamic assemblies can get reclaimed as needed.280                t_searchedAssemblies.Clear();281            }282        }283 284        internal static Type ResolveAssemblyQualifiedTypeName(TypeName typeName, out Exception exception)285        {286            // If an assembly name was specified, we let Type.GetType deal with loading the assembly287            // and resolving the type.288            exception = null;289            try290            {291                // We shouldn't really bother looking for the type in System namespace, but292                // we've always done that.  We explicitly are not supporting arbitrary293                // 'using namespace' here because there is little value, if you need the assembly294                // qualifier, it's best to just fully specify the type.295                var result = Type.GetType(typeName.FullName, false, true) ??296                             Type.GetType("System." + typeName.FullName, false, true);297 298                if (result != null && IsPublic(result))299                {300                    return result;301                }302            }303            catch (Exception e)304            {305                exception = e;306            }307 308            return null;309        }310 311        internal static Type ResolveTypeNameWithContext(TypeName typeName, out Exception exception, Assembly[] assemblies, TypeResolutionState typeResolutionState)312        {313            ExecutionContext context = null;314            exception = null;315 316            if (typeResolutionState == null)317            {318                // Usings from script scope (and if no script scope, fall back to default 'using namespace system')319                context = LocalPipeline.GetExecutionContextFromTLS();320                typeResolutionState = TypeResolutionState.GetDefaultUsingState(context);321            }322 323            // We can do the cache lookup only if we don't define type in the current scope (cache would be invalid in this case).324            var result = typeResolutionState.ContainsTypeDefined(typeName.Name)325                ? null326                : TypeCache.Lookup(typeName, typeResolutionState);327            if (result != null)328            {329                return result;330            }331 332            if (typeName.AssemblyName != null)333            {334                result = ResolveAssemblyQualifiedTypeName(typeName, out exception);335                TypeCache.Add(typeName, typeResolutionState, result);336                return result;337            }338 339            // Simple typename (no generics, no arrays, no assembly name)340            // We use the following search order, using the specified name (assumed to be fully namespace qualified):341            //342            //     * Search scope table (includes 'using type x = ...' aliases)343            //     * Built in type accelerators (implicit 'using type x = ...' aliases that are effectively in global scope344            //     * typeResolutionState.assemblies, which contains:345            //          - Assemblies with PS types, added by 'using module'346            //          - Assemblies added by 'using assembly'.347            //          For this case, we REPORT ambiguity, since user explicitly specifies the set of assemblies.348            //     * All other loaded assemblies (excluding dynamic assemblies created for PS defined types).349            //          IGNORE ambiguity. It mimics PS v4. There are two reasons:350            //          1) If we report ambiguity, we need to fix our caching logic accordingly.351            //             Consider this code352            //                  Add-Type 'public class Q {}' # ok353            //                  Add-Type 'public class Q { }' # get error about the same name354            //                  [Q] # we would get error about ambiguous type, because we added assembly with duplicated type355            //                      # before we can report TYPE_ALREADY_EXISTS error.356            //357            //                  Add-Type 'public class Q2 {}' # ok358            //                  [Q2] # caching Q2 type359            //                  Add-Type 'public class Q2 { }' # get error about the same name360            //                  [Q2] # we don't get an error about ambiguous type, because it's cached already361            //          2) NuGet (VS Package Management console) uses MEF extensibility model.362            //             Different assemblies includes same interface (i.e. NuGet.VisualStudio.IVsPackageInstallerServices),363            //             where they include only methods that they are interested in the interface declaration (result interfaces are different!).364            //             Then, at runtime VS provides an instance. Everything work as far as instance has compatible API.365            //             So [NuGet.VisualStudio.IVsPackageInstallerServices] can be resolved to several different assemblies and it's ok.366            //     * User defined type accelerators (rare - interface was never public)367            //368            // If nothing is found, we search again, this time applying any 'using namespace ...' declarations including the implicit 'using namespace System'.369            // We must search all using aliases and REPORT an error if there is an ambiguity.370 371            // If this is TypeDefinition we should not cache anything in TypeCache.372            if (typeName._typeDefinitionAst != null)373            {374                return typeName._typeDefinitionAst.Type;375            }376 377            context ??= LocalPipeline.GetExecutionContextFromTLS();378 379            // Use the explicitly passed-in assembly list when it's specified by the caller.380            // Otherwise, retrieve all currently loaded assemblies.381            var assemList = assemblies ?? ClrFacade.GetAssemblies(typeResolutionState, typeName);382            var isAssembliesExplicitlyPassedIn = assemblies != null;383 384            result = CallResolveTypeNameWorkerHelper(typeName, context, assemList, isAssembliesExplicitlyPassedIn, typeResolutionState, out exception);385 386            if (result != null)387            {388                TypeCache.Add(typeName, typeResolutionState, result);389                return result;390            }391 392            if (exception == null)393            {394                foreach (var ns in typeResolutionState.namespaces)395                {396                    var newTypeNameToSearch = ns + "." + typeName.Name;397                    newTypeNameToSearch = typeResolutionState.GetAlternateTypeName(newTypeNameToSearch) ??398                                          newTypeNameToSearch;399                    var newTypeName = new TypeName(typeName.Extent, newTypeNameToSearch);400#if CORECLR401                    if (!isAssembliesExplicitlyPassedIn)402                    {403                        // We called 'ClrFacade.GetAssemblies' to get assemblies. That means the assemblies to search from404                        // are not pre-defined, and thus we have to refetch assembly again based on the new type name.405                        assemList = ClrFacade.GetAssemblies(typeResolutionState, newTypeName);406                    }407#endif408                    var newResult = CallResolveTypeNameWorkerHelper(newTypeName, context, assemList, isAssembliesExplicitlyPassedIn, typeResolutionState, out exception);409 410                    if (exception != null)411                    {412                        break;413                    }414 415                    if (newResult != null)416                    {417                        if (result == null)418                        {419                            result = newResult;420                        }421                        else422                        {423                            exception = new AmbiguousTypeException(typeName, new string[] { result.FullName, newResult.FullName });424                            result = null;425                            break;426                        }427                    }428                }429            }430 431            if (exception != null)432            {433                // AmbiguousTypeException is for internal representation only.434                var ambiguousException = exception as AmbiguousTypeException;435                if (ambiguousException != null)436                {437                    exception = new PSInvalidCastException("AmbiguousTypeReference", exception,438                    ParserStrings.AmbiguousTypeReference, ambiguousException.TypeName.Name,439                                    ambiguousException.Candidates[0], ambiguousException.Candidates[1]);440                }441            }442 443            if (result != null)444            {445                TypeCache.Add(typeName, typeResolutionState, result);446            }447 448            return result;449        }450 451        internal static Type ResolveTypeName(TypeName typeName, out Exception exception)452        {453            return ResolveTypeNameWithContext(typeName, out exception, null, null);454        }455 456        internal static bool TryResolveType(string typeName, out Type type)457        {458            Exception exception;459            type = ResolveType(typeName, out exception);460            return (type != null);461        }462 463        internal static Type ResolveITypeName(ITypeName iTypeName, out Exception exception)464        {465            exception = null;466            var typeName = iTypeName as TypeName;467            if (typeName == null)468            {469                // The type is something more complicated - generic or array.470                try471                {472                    return iTypeName.GetReflectionType();473                }474                catch (Exception e)475                {476                    exception = e;477                    return null;478                }479            }480 481            return ResolveTypeName(typeName, out exception);482        }483 484        /// <summary>485        /// This routine converts a string into a Type object using the msh rules.486        /// </summary>487        /// <param name="strTypeName">A string representing the name of the type to convert.</param>488        /// <param name="exception">The exception, if one happened, trying to find the type.</param>489        /// <returns>A type if the conversion was successful, null otherwise.</returns>490        internal static Type ResolveType(string strTypeName, out Exception exception)491        {492            exception = null;493            if (string.IsNullOrWhiteSpace(strTypeName))494            {495                return null;496            }497 498            var iTypeName = Parser.ScanType(strTypeName, ignoreErrors: false);499            if (iTypeName == null)500            {501                return null;502            }503 504            return ResolveITypeName(iTypeName, out exception);505        }506    }507 508    /// <summary>509    /// The idea behind this class is: I should be able to re-use expensive510    /// type resolution operation result in the same context.511    /// Hence, this class is a key for TypeCache dictionary.512    ///513    /// Every SessionStateScope has TypeResolutionState.514    /// typesDefined contains PowerShell types names defined in the current scope and all scopes above.515    /// Same for namespaces.516    ///517    /// If TypeResolutionState doesn't add anything new compare to it's parent, we represent it as null.518    /// So, when we do lookup, we need to find first non-null TypeResolutionState.519    /// </summary>520    internal class TypeResolutionState521    {522        internal static readonly string[] systemNamespace = { "System" };523        internal static readonly Assembly[] emptyAssemblies = Array.Empty<Assembly>();524        internal static readonly TypeResolutionState UsingSystem = new TypeResolutionState();525 526        internal readonly string[] namespaces;527        internal readonly Assembly[] assemblies;528        private readonly HashSet<string> _typesDefined;529        internal readonly int genericArgumentCount;530        internal readonly bool attribute;531 532        private TypeResolutionState()533            : this(systemNamespace, emptyAssemblies)534        {535        }536 537        /// <summary>538        /// TypeResolutionState can be shared and that's why it should be represented as an immutable object.539        /// So, we use this API to alternate TypeResolutionState, but instead of mutating existing one, we clone it.540        /// </summary>541        /// <param name="types"></param>542        /// <returns></returns>543        internal TypeResolutionState CloneWithAddTypesDefined(IEnumerable<string> types)544        {545            var newTypesDefined = new HashSet<string>(_typesDefined, StringComparer.OrdinalIgnoreCase);546            foreach (var type in types)547            {548                newTypesDefined.Add(type);549            }550 551            return new TypeResolutionState(this, newTypesDefined);552        }553 554        internal bool ContainsTypeDefined(string type)555        {556            return _typesDefined.Contains(type);557        }558 559        internal TypeResolutionState(string[] namespaces, Assembly[] assemblies)560        {561            this.namespaces = namespaces ?? systemNamespace;562            this.assemblies = assemblies ?? emptyAssemblies;563            _typesDefined = new HashSet<string>(StringComparer.OrdinalIgnoreCase);564        }565 566        internal TypeResolutionState(TypeResolutionState other, int genericArgumentCount, bool attribute)567        {568            this.namespaces = other.namespaces;569            this.assemblies = other.assemblies;570            _typesDefined = other._typesDefined;571            this.genericArgumentCount = genericArgumentCount;572            this.attribute = attribute;573        }574 575        private TypeResolutionState(TypeResolutionState other, HashSet<string> typesDefined)576        {577            this.namespaces = other.namespaces;578            this.assemblies = other.assemblies;579            _typesDefined = typesDefined;580            this.genericArgumentCount = other.genericArgumentCount;581            this.attribute = other.attribute;582        }583 584        internal static TypeResolutionState GetDefaultUsingState(ExecutionContext context)585        {586            context ??= LocalPipeline.GetExecutionContextFromTLS();587 588            if (context != null)589            {590                return context.EngineSessionState.CurrentScope.TypeResolutionState;591            }592 593            return TypeResolutionState.UsingSystem;594        }595 596        internal string GetAlternateTypeName(string typeName)597        {598            string alternateName = null;599            if (genericArgumentCount > 0 && typeName.IndexOf('`') < 0)600            {601                alternateName = typeName + "`" + genericArgumentCount;602            }603            else if (attribute && !typeName.EndsWith("Attribute", StringComparison.OrdinalIgnoreCase))604            {605                alternateName = typeName + "Attribute";606            }607 608            return alternateName;609        }610 611        public override bool Equals(object obj)612        {613            if (object.ReferenceEquals(this, obj))614                return true;615 616            if (!(obj is TypeResolutionState other))617                return false;618 619            if (this.attribute != other.attribute)620                return false;621 622            if (this.genericArgumentCount != other.genericArgumentCount)623                return false;624 625            if (this.namespaces.Length != other.namespaces.Length)626                return false;627 628            if (this.assemblies.Length != other.assemblies.Length)629                return false;630 631            for (int i = 0; i < namespaces.Length; i++)632            {633                if (!this.namespaces[i].Equals(other.namespaces[i], StringComparison.OrdinalIgnoreCase))634                    return false;635            }636 637            for (int i = 0; i < assemblies.Length; i++)638            {639                if (!this.assemblies[i].Equals(other.assemblies[i]))640                    return false;641            }642 643            if (_typesDefined.Count != other._typesDefined.Count)644                return false;645 646            return _typesDefined.SetEquals(other._typesDefined);647        }648 649        public override int GetHashCode()650        {651            var stringComparer = StringComparer.OrdinalIgnoreCase;652            int result = Utils.CombineHashCodes(genericArgumentCount.GetHashCode(), attribute.GetHashCode());653            for (int i = 0; i < namespaces.Length; i++)654            {655                result = Utils.CombineHashCodes(result, stringComparer.GetHashCode(namespaces[i]));656            }657 658            for (int i = 0; i < assemblies.Length; i++)659            {660                result = Utils.CombineHashCodes(result, this.assemblies[i].GetHashCode());661            }662 663            foreach (var t in _typesDefined)664            {665                result = Utils.CombineHashCodes(result, t.GetHashCode());666            }667 668            return result;669        }670    }671 672    internal static class TypeCache673    {674        private sealed class KeyComparer : IEqualityComparer<Tuple<ITypeName, TypeResolutionState>>675        {676            public bool Equals(Tuple<ITypeName, TypeResolutionState> x,677                               Tuple<ITypeName, TypeResolutionState> y)678            {679                return x.Item1.Equals(y.Item1) && x.Item2.Equals(y.Item2);680            }681 682            public int GetHashCode(Tuple<ITypeName, TypeResolutionState> obj)683            {684                return obj.GetHashCode();685            }686        }687 688        private static readonly ConcurrentDictionary<Tuple<ITypeName, TypeResolutionState>, Type> s_cache = new ConcurrentDictionary<Tuple<ITypeName, TypeResolutionState>, Type>(new KeyComparer());689 690        internal static Type Lookup(ITypeName typeName, TypeResolutionState typeResolutionState)691        {692            Type result;693            s_cache.TryGetValue(Tuple.Create(typeName, typeResolutionState), out result);694            return result;695        }696 697        internal static void Add(ITypeName typeName, TypeResolutionState typeResolutionState, Type type)698        {699            s_cache.GetOrAdd(Tuple.Create(typeName, typeResolutionState), type);700        }701    }702}703 704namespace System.Management.Automation705{706    /// <summary>707    /// A class to the core types in PowerShell.708    /// </summary>709    internal static class CoreTypes710    {711        // A list of the core PowerShell types, and their accelerator.712        //713        // These types are frequently used in scripting, and for parameter validation in scripts.714        //715        // When in ConstrainedLanguage mode, all operations on these types are fully supported unlike all other716        // types that are assumed to have dangerous constructors or methods.717        //718        // Do not add types to this pool unless they can be safely exposed to an attacker and will not719        // expose the ability to corrupt or escape PowerShell's environment. The following operations must720        // be safe: type conversion, all constructors, all methods (instance and static), and721        // and properties (instance and static).722        internal static readonly Lazy<Dictionary<Type, string[]>> Items = new Lazy<Dictionary<Type, string[]>>(723            () =>724                new Dictionary<Type, string[]>725                {726                    { typeof(AliasAttribute),                              new[] { "Alias" } },727                    { typeof(AllowEmptyCollectionAttribute),               new[] { "AllowEmptyCollection" } },728                    { typeof(AllowEmptyStringAttribute),                   new[] { "AllowEmptyString" } },729                    { typeof(AllowNullAttribute),                          new[] { "AllowNull" } },730                    { typeof(ArgumentCompleterAttribute),                  new[] { "ArgumentCompleter" } },731                    { typeof(ArgumentCompletionsAttribute),                new[] { "ArgumentCompletions" } },732                    { typeof(Array),                                       new[] { "array" } },733                    { typeof(bool),                                        new[] { "bool" } },734                    { typeof(byte),                                        new[] { "byte" } },735                    { typeof(char),                                        new[] { "char" } },736                    { typeof(CmdletBindingAttribute),                      new[] { "CmdletBinding" } },737                    { typeof(DateTime),                                    new[] { "datetime" } },738                    { typeof(decimal),                                     new[] { "decimal" } },739                    { typeof(double),                                      new[] { "double" } },740                    { typeof(DscResourceAttribute),                        new[] { "DscResource" } },741                    { typeof(ExperimentAction),                            new[] { "ExperimentAction" } },742                    { typeof(ExperimentalAttribute),                       new[] { "Experimental" } },743                    { typeof(ExperimentalFeature),                         new[] { "ExperimentalFeature" } },744                    { typeof(float),                                       new[] { "float", "single" } },745                    { typeof(Guid),                                        new[] { "guid" } },746                    { typeof(Hashtable),                                   new[] { "hashtable" } },747                    { typeof(int),                                         new[] { "int", "int32" } },748                    { typeof(Int16),                                       new[] { "short", "int16" } },749                    { typeof(long),                                        new[] { "long", "int64" } },750                    { typeof(CimInstance),                                 new[] { "ciminstance" } },751                    { typeof(CimClass),                                    new[] { "cimclass" } },752                    { typeof(Microsoft.Management.Infrastructure.CimType), new[] { "cimtype" } },753                    { typeof(CimConverter),                                new[] { "cimconverter" } },754                    { typeof(ModuleSpecification),                         null },755                    { typeof(IPEndPoint),                                  new[] { "IPEndpoint" } },756                    { typeof(NoRunspaceAffinityAttribute),                 new[] { "NoRunspaceAffinity" } },757                    { typeof(NullString),                                  new[] { "NullString" } },758                    { typeof(OutputTypeAttribute),                         new[] { "OutputType" } },759                    { typeof(object[]),                                    null },760                    { typeof(ObjectSecurity),                              new[] { "ObjectSecurity" } },761                    { typeof(OrderedDictionary),                           new[] { "ordered" } },762                    { typeof(ParameterAttribute),                          new[] { "Parameter" } },763                    { typeof(PhysicalAddress),                             new[] { "PhysicalAddress" } },764                    { typeof(PSCredential),                                new[] { "pscredential" } },765                    { typeof(PSDefaultValueAttribute),                     new[] { "PSDefaultValue" } },766                    { typeof(PSListModifier),                              new[] { "pslistmodifier" } },767                    { typeof(PSObject),                                    new[] { "psobject", "pscustomobject" } },768                    { typeof(PSPrimitiveDictionary),                       new[] { "psprimitivedictionary" } },769                    { typeof(PSReference),                                 new[] { "ref" } },770                    { typeof(PSTypeNameAttribute),                         new[] { "PSTypeNameAttribute" } },771                    { typeof(Regex),                                       new[] { "regex" } },772                    { typeof(DscPropertyAttribute),                        new[] { "DscProperty" } },773                    { typeof(sbyte),                                       new[] { "sbyte" } },774                    { typeof(string),                                      new[] { "string" } },775                    { typeof(SupportsWildcardsAttribute),                  new[] { "SupportsWildcards" } },776                    { typeof(SwitchParameter),                             new[] { "switch" } },777                    { typeof(CultureInfo),                                 new[] { "cultureinfo" } },778                    { typeof(BigInteger),                                  new[] { "bigint" } },779                    { typeof(SecureString),                                new[] { "securestring" } },780                    { typeof(TimeSpan),                                    new[] { "timespan" } },781                    { typeof(UInt16),                                      new[] { "ushort", "uint16" } },782                    { typeof(UInt32),                                      new[] { "uint", "uint32" } },783                    { typeof(UInt64),                                      new[] { "ulong", "uint64" } },784                    { typeof(Uri),                                         new[] { "uri" } },785                    { typeof(ValidateCountAttribute),                      new[] { "ValidateCount" } },786                    { typeof(ValidateDriveAttribute),                      new[] { "ValidateDrive" } },787                    { typeof(ValidateLengthAttribute),                     new[] { "ValidateLength" } },788                    { typeof(ValidateNotNullAttribute),                    new[] { "ValidateNotNull" } },789                    { typeof(ValidateNotNullOrEmptyAttribute),             new[] { "ValidateNotNullOrEmpty" } },790                    { typeof(ValidateNotNullOrWhiteSpaceAttribute),        new[] { "ValidateNotNullOrWhiteSpace" } },791                    { typeof(ValidatePatternAttribute),                    new[] { "ValidatePattern" } },792                    { typeof(ValidateRangeAttribute),                      new[] { "ValidateRange" } },793                    { typeof(ValidateScriptAttribute),                     new[] { "ValidateScript" } },794                    { typeof(ValidateSetAttribute),                        new[] { "ValidateSet" } },795                    { typeof(ValidateTrustedDataAttribute),                new[] { "ValidateTrustedData" } },796                    { typeof(ValidateUserDriveAttribute),                  new[] { "ValidateUserDrive"} },797                    { typeof(Version),                                     new[] { "version" } },798                    { typeof(void),                                        new[] { "void" } },799                    { typeof(IPAddress),                                   new[] { "ipaddress" } },800                    { typeof(DscLocalConfigurationManagerAttribute),       new[] {"DscLocalConfigurationManager"}},801                    { typeof(WildcardPattern),                             new[] { "WildcardPattern" } },802                    { typeof(X509Certificate),                             new[] { "X509Certificate" } },803                    { typeof(X500DistinguishedName),                       new[] { "X500DistinguishedName" } },804                    { typeof(XmlDocument),                                 new[] { "xml" } },805                    { typeof(CimSession),                                  new[] { "CimSession" } },806                    { typeof(MailAddress),                                 new[] { "mailaddress" } },807                    { typeof(SemanticVersion),                             new[] { "semver" } },808#if !UNIX809                    { typeof(DirectoryEntry),                              new[] { "adsi" } },810                    { typeof(DirectorySearcher),                           new[] { "adsisearcher" } },811                    { typeof(ManagementClass),                             new[] { "wmiclass" } },812                    { typeof(ManagementObject),                            new[] { "wmi" } },813                    { typeof(ManagementObjectSearcher),                    new[] { "wmisearcher" } }814#endif815                }816            );817 818        internal static bool Contains(Type inputType)819        {820            if (Items.Value.ContainsKey(inputType))821            {822                return true;823            }824 825            if (inputType.IsEnum)826            {827                return true;828            }829 830            if (inputType.IsGenericType)831            {832                var genericTypeDefinition = inputType.GetGenericTypeDefinition();833                return genericTypeDefinition == typeof(Nullable<>) || genericTypeDefinition == typeof(FlagsExpression<>);834            }835 836            return (inputType.IsArray && Contains(inputType.GetElementType()));837        }838    }839 840    /// <summary>841    /// A class to view and modify the type accelerators used by the PowerShell engine.  Builtin842    /// type accelerators are read only, but user defined type accelerators may be added.843    /// </summary>844    internal static class TypeAccelerators845    {846        // builtins are not exposed publicly in a direct manner so they can't be changed at all847        internal static readonly Dictionary<string, Type> builtinTypeAccelerators = new Dictionary<string, Type>(64, StringComparer.OrdinalIgnoreCase);848 849        // users can add to user added accelerators (but not currently remove any.)  Keeping a separate850        // list allows us to add removing in the future w/o worrying about breaking the builtins.851        internal static readonly Dictionary<string, Type> userTypeAccelerators = new Dictionary<string, Type>(64, StringComparer.OrdinalIgnoreCase);852 853        // We expose this one publicly for programmatic access to our type accelerator table, but it is854        // otherwise unused (so changes to this dictionary don't affect internals.)855        private static Dictionary<string, Type> s_allTypeAccelerators;856 857        static TypeAccelerators()858        {859            // Add all the core types860            foreach (KeyValuePair<Type, string[]> coreType in CoreTypes.Items.Value)861            {862                if (coreType.Value != null)863                {864                    foreach (string accelerator in coreType.Value)865                    {866                        builtinTypeAccelerators.Add(accelerator, coreType.Key);867                    }868                }869            }870 871            // Add additional utility types that are useful as type accelerators, but aren't872            // fundamentally "core language", or may be unsafe to expose to untrusted input.873            builtinTypeAccelerators.Add("scriptblock", typeof(ScriptBlock));874            builtinTypeAccelerators.Add("pspropertyexpression", typeof(PSPropertyExpression));875            builtinTypeAccelerators.Add("psvariable", typeof(PSVariable));876            builtinTypeAccelerators.Add("type", typeof(Type));877            builtinTypeAccelerators.Add("psmoduleinfo", typeof(PSModuleInfo));878            builtinTypeAccelerators.Add("powershell", typeof(PowerShell));879            builtinTypeAccelerators.Add("runspacefactory", typeof(RunspaceFactory));880            builtinTypeAccelerators.Add("runspace", typeof(Runspace));881            builtinTypeAccelerators.Add("initialsessionstate", typeof(InitialSessionState));882            builtinTypeAccelerators.Add("psscriptmethod", typeof(PSScriptMethod));883            builtinTypeAccelerators.Add("psscriptproperty", typeof(PSScriptProperty));884            builtinTypeAccelerators.Add("psnoteproperty", typeof(PSNoteProperty));885            builtinTypeAccelerators.Add("psaliasproperty", typeof(PSAliasProperty));886            builtinTypeAccelerators.Add("psvariableproperty", typeof(PSVariableProperty));887        }888 889        internal static string FindBuiltinAccelerator(Type type, string expectedKey = null)890        {891            // Taking attributes as special case. In this case, we only want to return the892            // accelerator.893            if (expectedKey == null || typeof(Attribute).IsAssignableFrom(type))894            {895                foreach (KeyValuePair<string, Type> entry in builtinTypeAccelerators)896                {897                    if (entry.Value == type)898                    {899                        return entry.Key;900                    }901                }902            }903            else904            {905                Type resultType = null;906                builtinTypeAccelerators.TryGetValue(expectedKey, out resultType);907                if (resultType != null && resultType == type)908                {909                    return expectedKey;910                }911            }912 913            return null;914        }915        /// <summary>916        /// Add a type accelerator.917        /// </summary>918        /// <param name="typeName">The type accelerator name.</param>919        /// <param name="type">The type of the type accelerator.</param>920        public static void Add(string typeName, Type type)921        {922            userTypeAccelerators[typeName] = type;923            if (s_allTypeAccelerators != null)924            {925                s_allTypeAccelerators[typeName] = type;926            }927        }928 929        /// <summary>930        /// Remove a type accelerator.931        /// </summary>932        /// <returns>True if the accelerator was removed, false otherwise.</returns>933        /// <param name="typeName">The accelerator to remove.</param>934        public static bool Remove(string typeName)935        {936            userTypeAccelerators.Remove(typeName);937            s_allTypeAccelerators?.Remove(typeName);938 939            return true;940        }941 942        /// <summary>943        /// This property is useful to tools that need to know what944        /// type accelerators are available (e.g. to allow for autocompletion.)945        /// </summary>946        /// <remarks>947        /// The returned dictionary should be treated as read only.  Changes made948        /// to the dictionary will not affect PowerShell scripts in any way.  Use949        /// <see cref="TypeAccelerators.Add"/> and950        /// <see cref="TypeAccelerators.Remove"/> to951        /// affect the type resolution in PowerShell scripts.952        /// </remarks>953        public static Dictionary<string, Type> Get954        {955            get956            {957                if (s_allTypeAccelerators == null)958                {959                    s_allTypeAccelerators = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);960                    FillCache(s_allTypeAccelerators);961                }962 963                return s_allTypeAccelerators;964            }965        }966 967        internal static void FillCache(Dictionary<string, Type> cache)968        {969            foreach (KeyValuePair<string, Type> val in builtinTypeAccelerators)970            {971                cache.Add(val.Key, val.Value);972            }973 974            foreach (KeyValuePair<string, Type> val in userTypeAccelerators)975            {976                cache.Add(val.Key, val.Value);977            }978        }979    }980}981