TypeNameParser.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / TypeNameParser.cs / 1305376 / TypeNameParser.cs

                            using System; 
using System.Diagnostics.Contracts;
using System.IO;
using System.Reflection;
using System.Security; 
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; 
using System.Text; 
using System.Threading;
using System.Runtime.Versioning; 
using Microsoft.Win32.SafeHandles;

#if !FEATURE_CORECLR
namespace System 
{
    [SecurityCritical] 
    internal class SafeTypeNameParserHandle : SafeHandleZeroOrMinusOneIsInvalid 
    {
        #region QCalls 
        [SecurityCritical]
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity] 
        private static extern void _ReleaseTypeNameParser(IntPtr pTypeNameParser);
        #endregion 
 
        public SafeTypeNameParserHandle()
            : base(true) 
        {
        }

        [SecurityCritical] 
        protected override bool ReleaseHandle()
        { 
            _ReleaseTypeNameParser(handle); 
            handle = IntPtr.Zero;
            return true; 
        }
    }

    internal sealed class TypeNameParser : IDisposable 
    {
        #region QCalls 
        [SecurityCritical] 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity]
        private static extern void _CreateTypeNameParser(string typeName, ObjectHandleOnStack retHandle, bool throwOnError);

        [SecurityCritical] 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity] 
        private static extern void _GetNames(SafeTypeNameParserHandle pTypeNameParser, ObjectHandleOnStack retArray);
 
        [SecurityCritical]
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity] 
        private static extern void _GetTypeArguments(SafeTypeNameParserHandle pTypeNameParser, ObjectHandleOnStack retArray);
 
        [SecurityCritical] 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity]
        private static extern void _GetModifiers(SafeTypeNameParserHandle pTypeNameParser, ObjectHandleOnStack retArray);

        [SecurityCritical] 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity] 
        private static extern void _GetAssemblyName(SafeTypeNameParserHandle pTypeNameParser, StringHandleOnStack retString);
        #endregion 

        #region Static Members
        [SecuritySafeCritical]
        internal static Type GetType( 
            string typeName,
            Func assemblyResolver, 
            Func typeResolver, 
            bool throwOnError,
            bool ignoreCase, 
            ref StackCrawlMark stackMark)
        {
            if (typeName == null)
                throw new ArgumentNullException("typeName"); 
            if (typeName.Length > 0 && typeName[0] == '\0')
                throw new ArgumentException(Environment.GetResourceString("Format_StringZeroLength")); 
            Contract.EndContractBlock(); 

            Type ret = null; 

            SafeTypeNameParserHandle handle = CreateTypeNameParser(typeName, throwOnError);

            if (handle != null) 
            {
                // If we get here the typeName must have been successfully parsed. 
                // Let's construct the Type object. 
                using (TypeNameParser parser = new TypeNameParser(handle))
                { 
                    ret = parser.ConstructType(assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
                }
            }
 
            return ret;
        } 
        #endregion 

        #region Private Data Members 
        private SafeTypeNameParserHandle m_NativeParser;
        private static readonly char[] SPECIAL_CHARS = {',', '[', ']', '&', '*', '+', '\\'}; /* see typeparse.h */
        #endregion
 
        #region Constructor and Disposer
        [SecuritySafeCritical] 
        private TypeNameParser(SafeTypeNameParserHandle handle) 
        {
            m_NativeParser = handle; 
        }

        [SecuritySafeCritical]
        public void Dispose() 
        {
            m_NativeParser.Dispose(); 
        } 
        #endregion
 
        #region private Members
        [SecuritySafeCritical]
        private unsafe Type ConstructType(
            Func assemblyResolver, 
            Func typeResolver,
            bool throwOnError, 
            bool ignoreCase, 
            ref StackCrawlMark stackMark)
        { 
            // assembly name
            Assembly assembly = null;
            string asmName = GetAssemblyName();
 
            // GetAssemblyName never returns null
            Contract.Assert(asmName != null); 
 
            if (asmName.Length > 0)
            { 
                assembly = ResolveAssembly(asmName, assemblyResolver, throwOnError, ref stackMark);

                if (assembly == null)
                { 
                    // Cannot resolve the assembly. If throwOnError is true we should have already thrown.
                    return null; 
                } 
            }
 
            string[] names = GetNames();
            if (names == null)
            {
                // This can only happen if the type name is an empty string or if the first char is '\0' 
                if (throwOnError)
                    throw new TypeLoadException(Environment.GetResourceString("Arg_TypeLoadNullStr")); 
 
                return null;
            } 

            Type baseType = ResolveType(assembly, names, typeResolver, throwOnError, ignoreCase, ref stackMark);

            if (baseType == null) 
            {
                // Cannot resolve the type. If throwOnError is true we should have already thrown. 
                Contract.Assert(throwOnError == false); 
                return null;
            } 

            SafeTypeNameParserHandle[] typeArguments = GetTypeArguments();

            Type[] types = null; 
            if (typeArguments != null)
            { 
                types = new Type[typeArguments.Length]; 
                for (int i = 0; i < typeArguments.Length; i++)
                { 
                    Contract.Assert(typeArguments[i] != null);

                    using (TypeNameParser argParser = new TypeNameParser(typeArguments[i]))
                    { 
                        types[i] = argParser.ConstructType(assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
                    } 
 
                    if (types[i] == null)
                    { 
                        // If throwOnError is true argParser.ConstructType should have already thrown.
                        Contract.Assert(throwOnError == false);
                        return null;
                    } 
                }
            } 
 
            int[] modifiers = GetModifiers();
 
            fixed (int* ptr = modifiers)
            {
                IntPtr intPtr = new IntPtr(ptr);
                return RuntimeTypeHandle.GetTypeHelper(baseType, types, intPtr, modifiers == null ? 0 : modifiers.Length); 
            }
        } 
 
        [SecuritySafeCritical]
        private static Assembly ResolveAssembly(string asmName, Func assemblyResolver, bool throwOnError, ref StackCrawlMark stackMark) 
        {
            Contract.Requires(asmName != null && asmName.Length > 0);

            Assembly assembly = null; 

            if (assemblyResolver == null) 
            { 
                if (throwOnError)
                { 
                    assembly = RuntimeAssembly.InternalLoad(asmName, null, ref stackMark, false /*forIntrospection*/);
                }
                else
                { 
                    // When throwOnError is false we should only catch FileNotFoundException.
                    // Other exceptions like BadImangeFormatException should still fly. 
                    try 
                    {
                        assembly = RuntimeAssembly.InternalLoad(asmName, null, ref stackMark, false /*forIntrospection*/); 
                    }
                    catch (FileNotFoundException)
                    {
                        return null; 
                    }
                } 
            } 
            else
            { 
                assembly = assemblyResolver(new AssemblyName(asmName));
                if (assembly == null && throwOnError)
                {
                    throw new FileNotFoundException(Environment.GetResourceString("FileNotFound_ResolveAssembly", asmName)); 
                }
            } 
 
            return assembly;
        } 

        private static Type ResolveType(Assembly assembly, string[] names, Func typeResolver, bool throwOnError, bool ignoreCase, ref StackCrawlMark stackMark)
        {
            Contract.Requires(names != null && names.Length > 0); 

            Type type = null; 
 
            // both the customer provided and the default type resolvers accept escaped type names
            string OuterMostTypeName = EscapeTypeName(names[0]); 

            // Resolve the top level type.
            if (typeResolver != null)
            { 
                type = typeResolver(assembly, OuterMostTypeName, ignoreCase);
 
                if (type == null && throwOnError) 
                {
                    string errorString = assembly == null ? 
                        Environment.GetResourceString("TypeLoad_ResolveType", OuterMostTypeName) :
                        Environment.GetResourceString("TypeLoad_ResolveTypeFromAssembly", OuterMostTypeName, assembly.FullName);

                    throw new TypeLoadException(errorString); 
                }
            } 
            else 
            {
                if (assembly == null) 
                {
                    type = RuntimeType.GetType(OuterMostTypeName, throwOnError, ignoreCase, false, ref stackMark);
                }
                else 
                {
                    type = assembly.GetType(OuterMostTypeName, throwOnError, ignoreCase); 
                } 
            }
 
            // Resolve nested types.
            if (type != null)
            {
                BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public; 
                if (ignoreCase)
                    bindingFlags |= BindingFlags.IgnoreCase; 
 
                for (int i = 1; i < names.Length; i++)
                { 
                    type = type.GetNestedType(names[i], bindingFlags);

                    if (type == null)
                    { 
                        if (throwOnError)
                            throw new TypeLoadException(Environment.GetResourceString("TypeLoad_ResolveNestedType", names[i], names[i-1])); 
                        else 
                            break;
                    } 
                }
            }

            return type; 
        }
 
        private static string EscapeTypeName(string name) 
        {
            if (name.IndexOfAny(SPECIAL_CHARS) < 0) 
                return name;

            StringBuilder sb = new StringBuilder();
            foreach (char c in name) 
            {
                if (Array.IndexOf(SPECIAL_CHARS, c) >= 0) 
                    sb.Append('\\'); 

                sb.Append(c); 
            }

            return sb.ToString();
        } 

        [SecuritySafeCritical] 
        private static SafeTypeNameParserHandle CreateTypeNameParser(string typeName, bool throwOnError) 
        {
            SafeTypeNameParserHandle retHandle = null; 
            _CreateTypeNameParser(typeName, JitHelpers.GetObjectHandleOnStack(ref retHandle), throwOnError);

            return retHandle;
        } 

        [SecuritySafeCritical] 
        private string[] GetNames() 
        {
            string[] names = null; 
            _GetNames(m_NativeParser, JitHelpers.GetObjectHandleOnStack(ref names));

            return names;
        } 

        [SecuritySafeCritical] 
        private SafeTypeNameParserHandle[] GetTypeArguments() 
        {
            SafeTypeNameParserHandle[] arguments = null; 
            _GetTypeArguments(m_NativeParser, JitHelpers.GetObjectHandleOnStack(ref arguments));

            return arguments;
        } 

        [SecuritySafeCritical] 
        private int[] GetModifiers() 
        {
            int[] modifiers = null; 
            _GetModifiers(m_NativeParser, JitHelpers.GetObjectHandleOnStack(ref modifiers));

            return modifiers;
        } 

        [SecuritySafeCritical] 
        private string GetAssemblyName() 
        {
            string assemblyName = null; 
            _GetAssemblyName(m_NativeParser, JitHelpers.GetStringHandleOnStack(ref assemblyName));

            return assemblyName;
        } 
        #endregion
    } 
} 
#endif //!FEATURE_CORECLR

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System; 
using System.Diagnostics.Contracts;
using System.IO;
using System.Reflection;
using System.Security; 
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; 
using System.Text; 
using System.Threading;
using System.Runtime.Versioning; 
using Microsoft.Win32.SafeHandles;

#if !FEATURE_CORECLR
namespace System 
{
    [SecurityCritical] 
    internal class SafeTypeNameParserHandle : SafeHandleZeroOrMinusOneIsInvalid 
    {
        #region QCalls 
        [SecurityCritical]
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity] 
        private static extern void _ReleaseTypeNameParser(IntPtr pTypeNameParser);
        #endregion 
 
        public SafeTypeNameParserHandle()
            : base(true) 
        {
        }

        [SecurityCritical] 
        protected override bool ReleaseHandle()
        { 
            _ReleaseTypeNameParser(handle); 
            handle = IntPtr.Zero;
            return true; 
        }
    }

    internal sealed class TypeNameParser : IDisposable 
    {
        #region QCalls 
        [SecurityCritical] 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity]
        private static extern void _CreateTypeNameParser(string typeName, ObjectHandleOnStack retHandle, bool throwOnError);

        [SecurityCritical] 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity] 
        private static extern void _GetNames(SafeTypeNameParserHandle pTypeNameParser, ObjectHandleOnStack retArray);
 
        [SecurityCritical]
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity] 
        private static extern void _GetTypeArguments(SafeTypeNameParserHandle pTypeNameParser, ObjectHandleOnStack retArray);
 
        [SecurityCritical] 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity]
        private static extern void _GetModifiers(SafeTypeNameParserHandle pTypeNameParser, ObjectHandleOnStack retArray);

        [SecurityCritical] 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity] 
        private static extern void _GetAssemblyName(SafeTypeNameParserHandle pTypeNameParser, StringHandleOnStack retString);
        #endregion 

        #region Static Members
        [SecuritySafeCritical]
        internal static Type GetType( 
            string typeName,
            Func assemblyResolver, 
            Func typeResolver, 
            bool throwOnError,
            bool ignoreCase, 
            ref StackCrawlMark stackMark)
        {
            if (typeName == null)
                throw new ArgumentNullException("typeName"); 
            if (typeName.Length > 0 && typeName[0] == '\0')
                throw new ArgumentException(Environment.GetResourceString("Format_StringZeroLength")); 
            Contract.EndContractBlock(); 

            Type ret = null; 

            SafeTypeNameParserHandle handle = CreateTypeNameParser(typeName, throwOnError);

            if (handle != null) 
            {
                // If we get here the typeName must have been successfully parsed. 
                // Let's construct the Type object. 
                using (TypeNameParser parser = new TypeNameParser(handle))
                { 
                    ret = parser.ConstructType(assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
                }
            }
 
            return ret;
        } 
        #endregion 

        #region Private Data Members 
        private SafeTypeNameParserHandle m_NativeParser;
        private static readonly char[] SPECIAL_CHARS = {',', '[', ']', '&', '*', '+', '\\'}; /* see typeparse.h */
        #endregion
 
        #region Constructor and Disposer
        [SecuritySafeCritical] 
        private TypeNameParser(SafeTypeNameParserHandle handle) 
        {
            m_NativeParser = handle; 
        }

        [SecuritySafeCritical]
        public void Dispose() 
        {
            m_NativeParser.Dispose(); 
        } 
        #endregion
 
        #region private Members
        [SecuritySafeCritical]
        private unsafe Type ConstructType(
            Func assemblyResolver, 
            Func typeResolver,
            bool throwOnError, 
            bool ignoreCase, 
            ref StackCrawlMark stackMark)
        { 
            // assembly name
            Assembly assembly = null;
            string asmName = GetAssemblyName();
 
            // GetAssemblyName never returns null
            Contract.Assert(asmName != null); 
 
            if (asmName.Length > 0)
            { 
                assembly = ResolveAssembly(asmName, assemblyResolver, throwOnError, ref stackMark);

                if (assembly == null)
                { 
                    // Cannot resolve the assembly. If throwOnError is true we should have already thrown.
                    return null; 
                } 
            }
 
            string[] names = GetNames();
            if (names == null)
            {
                // This can only happen if the type name is an empty string or if the first char is '\0' 
                if (throwOnError)
                    throw new TypeLoadException(Environment.GetResourceString("Arg_TypeLoadNullStr")); 
 
                return null;
            } 

            Type baseType = ResolveType(assembly, names, typeResolver, throwOnError, ignoreCase, ref stackMark);

            if (baseType == null) 
            {
                // Cannot resolve the type. If throwOnError is true we should have already thrown. 
                Contract.Assert(throwOnError == false); 
                return null;
            } 

            SafeTypeNameParserHandle[] typeArguments = GetTypeArguments();

            Type[] types = null; 
            if (typeArguments != null)
            { 
                types = new Type[typeArguments.Length]; 
                for (int i = 0; i < typeArguments.Length; i++)
                { 
                    Contract.Assert(typeArguments[i] != null);

                    using (TypeNameParser argParser = new TypeNameParser(typeArguments[i]))
                    { 
                        types[i] = argParser.ConstructType(assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
                    } 
 
                    if (types[i] == null)
                    { 
                        // If throwOnError is true argParser.ConstructType should have already thrown.
                        Contract.Assert(throwOnError == false);
                        return null;
                    } 
                }
            } 
 
            int[] modifiers = GetModifiers();
 
            fixed (int* ptr = modifiers)
            {
                IntPtr intPtr = new IntPtr(ptr);
                return RuntimeTypeHandle.GetTypeHelper(baseType, types, intPtr, modifiers == null ? 0 : modifiers.Length); 
            }
        } 
 
        [SecuritySafeCritical]
        private static Assembly ResolveAssembly(string asmName, Func assemblyResolver, bool throwOnError, ref StackCrawlMark stackMark) 
        {
            Contract.Requires(asmName != null && asmName.Length > 0);

            Assembly assembly = null; 

            if (assemblyResolver == null) 
            { 
                if (throwOnError)
                { 
                    assembly = RuntimeAssembly.InternalLoad(asmName, null, ref stackMark, false /*forIntrospection*/);
                }
                else
                { 
                    // When throwOnError is false we should only catch FileNotFoundException.
                    // Other exceptions like BadImangeFormatException should still fly. 
                    try 
                    {
                        assembly = RuntimeAssembly.InternalLoad(asmName, null, ref stackMark, false /*forIntrospection*/); 
                    }
                    catch (FileNotFoundException)
                    {
                        return null; 
                    }
                } 
            } 
            else
            { 
                assembly = assemblyResolver(new AssemblyName(asmName));
                if (assembly == null && throwOnError)
                {
                    throw new FileNotFoundException(Environment.GetResourceString("FileNotFound_ResolveAssembly", asmName)); 
                }
            } 
 
            return assembly;
        } 

        private static Type ResolveType(Assembly assembly, string[] names, Func typeResolver, bool throwOnError, bool ignoreCase, ref StackCrawlMark stackMark)
        {
            Contract.Requires(names != null && names.Length > 0); 

            Type type = null; 
 
            // both the customer provided and the default type resolvers accept escaped type names
            string OuterMostTypeName = EscapeTypeName(names[0]); 

            // Resolve the top level type.
            if (typeResolver != null)
            { 
                type = typeResolver(assembly, OuterMostTypeName, ignoreCase);
 
                if (type == null && throwOnError) 
                {
                    string errorString = assembly == null ? 
                        Environment.GetResourceString("TypeLoad_ResolveType", OuterMostTypeName) :
                        Environment.GetResourceString("TypeLoad_ResolveTypeFromAssembly", OuterMostTypeName, assembly.FullName);

                    throw new TypeLoadException(errorString); 
                }
            } 
            else 
            {
                if (assembly == null) 
                {
                    type = RuntimeType.GetType(OuterMostTypeName, throwOnError, ignoreCase, false, ref stackMark);
                }
                else 
                {
                    type = assembly.GetType(OuterMostTypeName, throwOnError, ignoreCase); 
                } 
            }
 
            // Resolve nested types.
            if (type != null)
            {
                BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public; 
                if (ignoreCase)
                    bindingFlags |= BindingFlags.IgnoreCase; 
 
                for (int i = 1; i < names.Length; i++)
                { 
                    type = type.GetNestedType(names[i], bindingFlags);

                    if (type == null)
                    { 
                        if (throwOnError)
                            throw new TypeLoadException(Environment.GetResourceString("TypeLoad_ResolveNestedType", names[i], names[i-1])); 
                        else 
                            break;
                    } 
                }
            }

            return type; 
        }
 
        private static string EscapeTypeName(string name) 
        {
            if (name.IndexOfAny(SPECIAL_CHARS) < 0) 
                return name;

            StringBuilder sb = new StringBuilder();
            foreach (char c in name) 
            {
                if (Array.IndexOf(SPECIAL_CHARS, c) >= 0) 
                    sb.Append('\\'); 

                sb.Append(c); 
            }

            return sb.ToString();
        } 

        [SecuritySafeCritical] 
        private static SafeTypeNameParserHandle CreateTypeNameParser(string typeName, bool throwOnError) 
        {
            SafeTypeNameParserHandle retHandle = null; 
            _CreateTypeNameParser(typeName, JitHelpers.GetObjectHandleOnStack(ref retHandle), throwOnError);

            return retHandle;
        } 

        [SecuritySafeCritical] 
        private string[] GetNames() 
        {
            string[] names = null; 
            _GetNames(m_NativeParser, JitHelpers.GetObjectHandleOnStack(ref names));

            return names;
        } 

        [SecuritySafeCritical] 
        private SafeTypeNameParserHandle[] GetTypeArguments() 
        {
            SafeTypeNameParserHandle[] arguments = null; 
            _GetTypeArguments(m_NativeParser, JitHelpers.GetObjectHandleOnStack(ref arguments));

            return arguments;
        } 

        [SecuritySafeCritical] 
        private int[] GetModifiers() 
        {
            int[] modifiers = null; 
            _GetModifiers(m_NativeParser, JitHelpers.GetObjectHandleOnStack(ref modifiers));

            return modifiers;
        } 

        [SecuritySafeCritical] 
        private string GetAssemblyName() 
        {
            string assemblyName = null; 
            _GetAssemblyName(m_NativeParser, JitHelpers.GetStringHandleOnStack(ref assemblyName));

            return assemblyName;
        } 
        #endregion
    } 
} 
#endif //!FEATURE_CORECLR

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK