TypeProvider.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 / cdf / src / WF / Common / AuthoringOM / Compiler / TypeSystem / TypeProvider.cs / 1305376 / TypeProvider.cs

                            #pragma warning disable 1634, 1691 
namespace System.Workflow.ComponentModel.Compiler
{
 	using System;
	using System.CodeDom; 
	using System.Collections;
	using System.Collections.Specialized; 
 	using System.Collections.Generic; 
	using System.Diagnostics;
 	using System.Resources; 
 	using System.Reflection;
	using System.Globalization;
 	using System.IO;
    using System.Text.RegularExpressions; 

	public sealed class TypeProvider : ITypeProvider, IServiceProvider, IDisposable 
	{ 
		internal static readonly char[] nameSeparators = new char[]{'.', '+'};
 
 		private IServiceProvider	serviceProvider = null;

		private Hashtable designTimeTypes		= new Hashtable();
 		private Hashtable assemblyLoaders		= new Hashtable(); 
 		private Hashtable rawAssemblyLoaders	= new Hashtable();
		private Hashtable compileUnitLoaders	= new Hashtable(); 
        private Hashtable hashOfRTTypes         = new Hashtable(); 
 		private Hashtable hashOfDTTypes			= new Hashtable();
 
		// these variables will cache all the information which is passed to
		private List			addedAssemblies =  null;
		private List	addedCompileUnits = null;
 		private Dictionary needRefreshCompileUnits = null;				 
		private bool					executingEnsureCurrentTypes = false;
 		private Hashtable				typeLoadErrors = new Hashtable(); 
 		private Assembly				localAssembly = null; 

		public TypeProvider(IServiceProvider serviceProvider) 
 		{
			this.serviceProvider = serviceProvider;
		}
 
		#region Public methods
 
 		public void SetLocalAssembly(Assembly assembly) 
		{
 			this.localAssembly = assembly; 
 			if (this.TypesChanged != null)
				FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty });
 		}
 
		public void AddAssembly(Assembly assembly)
		{ 
			if (assembly == null) 
 				throw new ArgumentNullException("assembly");
 
			if (!rawAssemblyLoaders.Contains(assembly))
 			{
 				try
				{ 
 					rawAssemblyLoaders[assembly] = new AssemblyLoader(this, assembly, this.localAssembly == assembly);
					if (this.TypesChanged != null) 
						FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty }); 
				}
 				catch(Exception e) 
				{
 					this.typeLoadErrors[assembly.FullName] = e;
 					if (this.TypeLoadErrorsChanged != null)
						FireEventsNoThrow(this.TypeLoadErrorsChanged, new object[] { this, EventArgs.Empty }); 
 				}
			} 
		} 
		public void RemoveAssembly(Assembly assembly)
 		{ 
			if (assembly == null)
 				throw new ArgumentNullException("assembly");

 			AssemblyLoader assemblyLoader = (AssemblyLoader)this.rawAssemblyLoaders[assembly]; 
			if (assemblyLoader != null)
 			{ 
				this.rawAssemblyLoaders.Remove(assembly); 
				RemoveCachedAssemblyWrappedTypes(assembly);
 
				if (this.TypesChanged != null)
 					FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty });
			}
 		} 

 		public void AddAssemblyReference(string path) 
		{ 
 			if (path == null)
				throw new ArgumentNullException("path"); 

            if (File.Exists(path) &&
                !this.assemblyLoaders.ContainsKey(path) &&
				(this.addedAssemblies == null || !this.addedAssemblies.Contains(path))) 
			{
 				// lets put these changes into our cache 
				if (this.addedAssemblies == null) 
 					this.addedAssemblies = new List();
 				this.addedAssemblies.Add(path); 

				if (this.TypesChanged != null)
 					FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty });
			} 
		}
		public void RemoveAssemblyReference(string path) 
 		{ 
			if (path == null)
 				throw new ArgumentNullException("path"); 

 			AssemblyLoader assemblyLoader = this.assemblyLoaders[path] as AssemblyLoader;
			if (assemblyLoader != null)
 			{ 
				this.assemblyLoaders.Remove(path);
				RemoveCachedAssemblyWrappedTypes(assemblyLoader.Assembly); 
			} 

 			if (this.addedAssemblies != null && this.addedAssemblies.Contains(path)) 
				this.addedAssemblies.Remove(path);

 			if (this.typeLoadErrors.ContainsKey(path))
 			{ 
				this.typeLoadErrors.Remove(path);
 				if (this.TypeLoadErrorsChanged != null) 
					FireEventsNoThrow(this.TypeLoadErrorsChanged, new object[] { this, EventArgs.Empty }); 
			}
 
			if (this.TypesChanged != null)
 				FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty });
		}
 		public void AddCodeCompileUnit(CodeCompileUnit codeCompileUnit) 
 		{
			if (codeCompileUnit == null) 
 				throw new ArgumentNullException("codeCompileUnit"); 

			if (this.compileUnitLoaders.ContainsKey(codeCompileUnit) || (this.addedCompileUnits != null && this.addedCompileUnits.Contains(codeCompileUnit))) 
				throw new ArgumentException(TypeSystemSR.GetString("Error_DuplicateCodeCompileUnit"), "codeCompileUnit");

			// lets put these changes into our cache
 			if (this.addedCompileUnits == null) 
				this.addedCompileUnits = new List();
 			this.addedCompileUnits.Add(codeCompileUnit); 
 			if (this.needRefreshCompileUnits != null && this.needRefreshCompileUnits.ContainsKey(codeCompileUnit)) 
				this.needRefreshCompileUnits.Remove(codeCompileUnit);
 
 			if (this.TypesChanged != null)
				FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty });
		}
		public void RemoveCodeCompileUnit(CodeCompileUnit codeCompileUnit) 
 		{
			if (codeCompileUnit == null) 
 				throw new ArgumentNullException("codeCompileUnit"); 

 			// lets put these changes into our cache 
			CodeDomLoader codeDomLoader = this.compileUnitLoaders[codeCompileUnit] as CodeDomLoader;
 			if (codeDomLoader != null)
			{
				codeDomLoader.Dispose(); 
				this.compileUnitLoaders.Remove(codeCompileUnit);
 			} 
 
			if (this.addedCompileUnits != null && this.addedCompileUnits.Contains(codeCompileUnit))
 				this.addedCompileUnits.Remove(codeCompileUnit); 
 			if (this.needRefreshCompileUnits != null && this.needRefreshCompileUnits.ContainsKey(codeCompileUnit))
				this.needRefreshCompileUnits.Remove(codeCompileUnit);

 			if (this.typeLoadErrors.ContainsKey(codeCompileUnit)) 
			{
				this.typeLoadErrors.Remove(codeCompileUnit); 
				if (this.TypeLoadErrorsChanged != null) 
 					FireEventsNoThrow(this.TypeLoadErrorsChanged, new object[] { this, EventArgs.Empty });
			} 

 			if (this.TypesChanged != null)
 				FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty });
		} 
 		public void RefreshCodeCompileUnit(CodeCompileUnit codeCompileUnit, EventHandler refresher)
		{ 
			if (codeCompileUnit == null) 
				throw new ArgumentNullException("codeCompileUnit");
 
 			if (!this.compileUnitLoaders.Contains(codeCompileUnit) && (this.addedCompileUnits != null && !this.addedCompileUnits.Contains(codeCompileUnit)))
				throw new ArgumentException(TypeSystemSR.GetString("Error_NoCodeCompileUnit"), "codeCompileUnit");

 			if (this.needRefreshCompileUnits == null) 
 				this.needRefreshCompileUnits = new Dictionary();
			this.needRefreshCompileUnits[codeCompileUnit] = refresher; 
 
 			if (this.TypesChanged != null)
				FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty }); 
		}
        #endregion

        #region TargetFrameworkProvider Support 
        //
        // In general this func can be used by anyone that wants to configure TypeProvder 
        // to do non standard type to assembly name mapping 
        // Specifically this func is set by Microsoft.Workflow.VSDesigner when running within VS
        // The func encapsulates VS multi-targeting functionality so that System.Workflow.ComponentModel 
        // does not need to take a dependency on VS bits.
        public Func AssemblyNameResolver
        {
            get; 
            set;
        } 
        public Func IsSupportedPropertyResolver 
        {
            get; 
            set;
        }
        //
        // VS multi-targeting uses LMR which, unlike reflection, does not cache 
        // Caching in the caller (here) is critical for performance
        // GetAssemblyName, IsSupportedProperty provide both default behavior 
        // if *Resolver is null and a cache over the LMR methods behind the Resolvers 
        // Caches rely on a single Type universe and object equality however due to issues in reflection it is
        // possible to get redundant items in the cache.  This is because reflection may return different instances 
        // of PropertyInfo depending on what API is called.  This is rare but it can happen.  Worst case is
        // redundant entries in the cache; this will not cause incorrect behavior.
        Dictionary typeToAssemblyName = null;
        Dictionary supportedProperties = null; 

        public string GetAssemblyName(Type type) 
        { 
            if (type == null)
            { 
                throw new ArgumentNullException("type");
            }

            if (typeToAssemblyName == null) 
            {
                typeToAssemblyName = new Dictionary(); 
            } 

            string assemblyName = null; 
            if (!typeToAssemblyName.TryGetValue(type, out assemblyName))
            {
                //
                // DesignTimeType will not have an assembly 
                if (type.Assembly != null)
                { 
                    if (this.AssemblyNameResolver != null) 
                    {
                        assemblyName = this.AssemblyNameResolver(type); 
                    }
                    else
                    {
                        assemblyName = type.Assembly.FullName; 
                    }
                    typeToAssemblyName.Add(type, assemblyName); 
                } 
            }
 
            if (assemblyName == null)
            {
                assemblyName = string.Empty;
            } 

            return assemblyName; 
        } 

        public bool IsSupportedProperty(PropertyInfo property, object declaringInstance) 
        {
            if (property == null)
            {
                throw new ArgumentNullException("property"); 
            }
            if (declaringInstance == null) 
            { 
                throw new ArgumentNullException("declaringInstance");
            } 
            //
            // If we don't have a resolver to determine if a property is supported
            // just return true
            if (IsSupportedPropertyResolver == null) 
            {
                return true; 
            } 

            if (supportedProperties == null) 
            {
                supportedProperties = new Dictionary();
            }
 
            bool supported = false;
            if (!supportedProperties.TryGetValue(property, out supported)) 
            { 
                supported = IsSupportedPropertyResolver(property, declaringInstance);
                supportedProperties.Add(property, supported); 
            }

            return supported;
        } 

        #endregion 
 
        #region ITypeProvider Members
 
        public Type GetType(string name)
		{
 			if (name == null)
				throw new ArgumentNullException("name"); 

 			return GetType(name, false); 
 		} 

		public Type GetType(string name, bool throwOnError) 
 		{
			if (name == null)
				throw new ArgumentNullException("name");
 
			EnsureCurrentTypes();
 			 
			bool hasTypeLoadErrors = false; 
 			Type returnType = null;
            string typeName = string.Empty; 
            string[] parameters = null;
 			string elementDecorator = string.Empty;

			if (ParseHelpers.ParseTypeName(name, ParseHelpers.ParseTypeNameLanguage.NetFramework, out typeName, out parameters, out elementDecorator)) 
 			{
                if ((parameters != null) && (parameters.Length > 0)) 
                { 
					//Generic type
                    Type templateType = GetType(typeName, throwOnError); 
                    if ((templateType == null) || (!templateType.IsGenericTypeDefinition))
                        return null;
                    Type[] templateParamTypes = new Type[parameters.Length];
                    for(int index = 0; index < parameters.Length; index++) 
                    {
                        Type templateParameter = GetType(parameters[index], throwOnError); 
                        if (templateParameter == null) 
                            return null;
                        templateParamTypes[index] = templateParameter; 
                    }
					return templateType.MakeGenericType(templateParamTypes);
                }
				else if (elementDecorator != string.Empty) 
 				{
					//type with element (Array, ByRef, Pointer) 
 					Type elementType = this.GetType(typeName); 
 					if (elementType != null)
					{ 
 						// first we verify the name is formated well (AssemblyQualifiedName for generic
						// parameters + no spaces in array brackets)
						System.Text.StringBuilder nameBuilder = new System.Text.StringBuilder(elementType.FullName);
						for (int loop = 0; loop < elementDecorator.Length; loop++) 
 							if (elementDecorator[loop] != ' ')
								nameBuilder.Append(elementDecorator[loop]); 
 
 						name = nameBuilder.ToString();
 
 						// let tha assembly of the element type a chance to find a type (will fail only
						// if element contains parameter from external assembly
 						if (elementType.Assembly != null)
							returnType = elementType.Assembly.GetType(name, false); 

						if (returnType == null) 
						{ 
 							// now we can fetch or create the type
							if (this.hashOfDTTypes.Contains(name)) 
 							{
 								returnType = this.hashOfDTTypes[name] as Type;
							}
 							else 
							{
								returnType = new DesignTimeType(null, name, this); 
								this.hashOfDTTypes.Add(name, returnType); 
 							}
                            return returnType; 
						}
 					}
 				}
				else 
 				{
					// regular type, get the type name 
					string assemblyName = string.Empty; 
					int indexOfComma = name.IndexOf(',');
 					if (indexOfComma != -1) 
					{
 						typeName = name.Substring(0, indexOfComma);
 						assemblyName = name.Substring(indexOfComma + 1).Trim();
					} 
 					typeName = typeName.Trim();
					if (typeName.Length > 0) 
					{ 
						returnType = this.designTimeTypes[typeName] as Type;
 						if (returnType == null) 
						{
 							foreach (DictionaryEntry dictionaryEntry in this.rawAssemblyLoaders)
 							{
								AssemblyLoader assemblyLoader = dictionaryEntry.Value as AssemblyLoader; 
 								if ((assemblyName.Length == 0) || (ParseHelpers.AssemblyNameEquals(assemblyLoader.AssemblyName, assemblyName)))
								{ 
									try 
									{
 										returnType = assemblyLoader.GetType(typeName); 
									}
 									catch (Exception e)
 									{
										if (!this.typeLoadErrors.Contains(dictionaryEntry.Key)) 
 										{
											this.typeLoadErrors[dictionaryEntry.Key] = e; 
											hasTypeLoadErrors = true; 
										}
 										// bubble up exceptions only when appropiate 
										if (throwOnError)
 											throw e;
 									}
									if (returnType != null) 
 										break;
								} 
							} 
						}
 						 
						if (returnType == null)
 						{
 							foreach (DictionaryEntry dictionaryEntry in this.assemblyLoaders)
							{ 
 								AssemblyLoader assemblyLoader = dictionaryEntry.Value as AssemblyLoader;
								if ((assemblyName.Length == 0) || (ParseHelpers.AssemblyNameEquals(assemblyLoader.AssemblyName, assemblyName))) 
								{ 
									try
 									{ 
										returnType = assemblyLoader.GetType(typeName);
 									}
 									catch (Exception e)
									{ 
 										if (!this.typeLoadErrors.Contains(dictionaryEntry.Key))
										{ 
											this.typeLoadErrors[dictionaryEntry.Key] = e; 
											hasTypeLoadErrors = true;
 										} 
										// bubble up exceptions only when appropiate
 										if (throwOnError)
 											throw e;
									} 
 									if (returnType != null)
										break; 
								} 
							}
 						} 

						if (hasTypeLoadErrors)
 						{
 							if (this.TypeLoadErrorsChanged != null) 
								FireEventsNoThrow(this.TypeLoadErrorsChanged, new object[] { this, EventArgs.Empty });
 						} 
 
						if (returnType == null && this.localAssembly != null && assemblyName == this.localAssembly.FullName)
							returnType = this.localAssembly.GetType(typeName); 
					}
 				}
			}
 
            if (returnType == null)
            { 
                if(throwOnError) 
                    throw new Exception(TypeSystemSR.GetString(CultureInfo.CurrentCulture, "Error_TypeResolution", name));
                else 
                    return null;
            }

            // replace the System.Type with RTTypeWrapper for generic types. 
            // WinOE Bug 16560: The type provider may be used at runtime.  No RTTypeWrapper should ever be returned
            // at runtime. 
            // At design time, we need to wrap all generic types even if the parameter types are not 
            // design time types.  This is because our parsing function creates a base generic type before it binds
            // all the parameters.  The RTTypeWrapper.MakeGenericType override will then take care of binding to 
            // design time types.
            if (this.designTimeTypes != null && this.designTimeTypes.Count > 0 && returnType.Assembly != null && returnType.IsGenericTypeDefinition)
            {
                if (this.hashOfRTTypes.Contains(returnType)) 
                {
                    returnType = (Type)this.hashOfRTTypes[returnType]; 
                } 
                else
                { 
                    Type returnType2 = new RTTypeWrapper(this, returnType);
                    this.hashOfRTTypes.Add(returnType, returnType2);
                    returnType = returnType2;
                } 
            }
            return returnType; 
 		} 

 		public Type[] GetTypes() 
		{
 			EnsureCurrentTypes();

			bool hasTypeLoadErrors = false; 
			this.typeLoadErrors.Clear();//clear all old errors
 
			List typeList = new List(); 

 			// Design time types 
			foreach (Type type in this.designTimeTypes.Values)
 					typeList.Add(type);

 			foreach (DictionaryEntry dictionaryEntry in this.assemblyLoaders) 
			{
 				AssemblyLoader assemblyLoader = dictionaryEntry.Value as AssemblyLoader; 
				try 
				{
					typeList.AddRange(assemblyLoader.GetTypes()); 
 				}
				catch (Exception e)
 				{
 					ReflectionTypeLoadException typeLoadException = e as ReflectionTypeLoadException; 
					if (typeLoadException != null)
 					{ 
						//we should at least add the types that did get loaded 
						foreach (Type type in typeLoadException.Types)
						{ 
 							if (type != null)
								typeList.Add(type);
 						}
 					} 

					//we should have the latest exception for every assembly (user might have copied required dlls over) 
 					if (this.typeLoadErrors.Contains(dictionaryEntry.Key)) 
						this.typeLoadErrors.Remove(dictionaryEntry.Key);
 
					this.typeLoadErrors[dictionaryEntry.Key] = e;
					hasTypeLoadErrors = true;
 				}
			} 

 			foreach (DictionaryEntry dictionaryEntry in this.rawAssemblyLoaders) 
 			{ 
				AssemblyLoader assemblyLoader = dictionaryEntry.Value as AssemblyLoader;
 				try 
				{
					typeList.AddRange(assemblyLoader.GetTypes());
				}
 				catch (Exception e) 
				{
 					ReflectionTypeLoadException typeLoadException = e as ReflectionTypeLoadException; 
 					if (typeLoadException != null) 
					{
 						//we should at least add the types that did get loaded 
						foreach (Type type in typeLoadException.Types)
						{
							if (type != null)
 								typeList.Add(type); 
						}
 					} 
 					//we should have the latest exception for every assembly (user might have copied required dlls over) 
					if (this.typeLoadErrors.Contains(dictionaryEntry.Key))
 						this.typeLoadErrors.Remove(dictionaryEntry.Key); 

					this.typeLoadErrors[dictionaryEntry.Key] = e;
					hasTypeLoadErrors = true;
				} 
 			}
 
			if (hasTypeLoadErrors) 
 			{
 				if (this.TypeLoadErrorsChanged != null) 
					FireEventsNoThrow(this.TypeLoadErrorsChanged, new object[] { this, EventArgs.Empty });
 			}

			return typeList.ToArray(); 
		}
 
		public IDictionary TypeLoadErrors 
 		{
			get 
 			{
 				Dictionary collection = new Dictionary();

				foreach (DictionaryEntry entry in this.typeLoadErrors) 
 				{
					Exception e = entry.Value as Exception; 
					while (e is TargetInvocationException) 
						e = e.InnerException;
 
 					if (e != null)
					{
 						string typeLoadError = null;
 
 						if (entry.Key is CodeCompileUnit)
							typeLoadError = TypeSystemSR.GetString("Error_CodeCompileUnitNotLoaded", new object[] { e.Message }); 
 						else if (entry.Key is String) 
							typeLoadError = TypeSystemSR.GetString("Error_AssemblyRefNotLoaded", new object[] { entry.Key.ToString(), e.Message });
 
						//wrap the original exception with a new one with a custom error message
						if (typeLoadError != null)
 							e = new Exception(typeLoadError, e);
 
						collection.Add(entry.Key, e);
 					} 
 				} 

				return collection; 
 			}
		}

		public Assembly LocalAssembly 
		{
 			get 
			{ 
 				return this.localAssembly;
 			} 
		}
 		public event EventHandler TypeLoadErrorsChanged;
		public event EventHandler TypesChanged;
 
        public ICollection ReferencedAssemblies
        { 
            get 
            {
                EnsureCurrentTypes(); 

                List referencedAssemblies = new List();
                foreach (AssemblyLoader loader in this.assemblyLoaders.Values)
                { 
                    if (loader.Assembly != null)
                        referencedAssemblies.Add(loader.Assembly); 
                } 

                foreach (Assembly assembly in this.rawAssemblyLoaders.Keys) 
                    referencedAssemblies.Add(assembly);

                return referencedAssemblies.AsReadOnly();
            } 
        }
 
		#endregion 

		#region TypeProvider Static Methods 

 		public static Type GetEventHandlerType(EventInfo eventInfo)
		{
 			if (eventInfo == null) 
 				throw new ArgumentNullException("eventInfo");
 
			MethodInfo m = eventInfo.GetAddMethod(true); 
            if (m != null)
            { 
                ParameterInfo[] p = m.GetParameters();
                Type del = typeof(Delegate);
                for (int i = 0; i < p.Length; i++)
                { 
                    Type c = p[i].ParameterType;
                    if (TypeProvider.IsSubclassOf(c, del)) 
                        return c; 
                }
            } 
 			return null;
		}

        internal static bool IsRepresentingTheSameType(Type firstType, Type secondType) 
        {
            if (firstType == null || secondType == null) 
                return false; 

            if (firstType == secondType) 
                return true;

            if (firstType.FullName != secondType.FullName)
                return false; 

            if (firstType.Assembly != secondType.Assembly) 
                return false; 

            if (firstType.Assembly != null) 
                if (firstType.AssemblyQualifiedName != secondType.AssemblyQualifiedName)
                    return false;

            return true; 
        }
 
		internal static bool IsAssignable(Type toType, Type fromType,bool equalBasedOnSameTypeRepresenting) 
		{
 			if (toType == null || fromType == null) 
				return false;

            if (equalBasedOnSameTypeRepresenting)
            { 
                if (IsRepresentingTheSameType(fromType, toType))
                    return true; 
            } 
            else
            { 
                if (fromType == toType)
                    return true;
            }
 
 			if (toType.IsGenericTypeDefinition)
 				return toType.IsAssignableFrom(fromType); 
 
			// runtime type can never be assigned to design time type
 			if (toType.Assembly == null && fromType.Assembly != null) 
				return false;
            if (fromType is RTTypeWrapper || fromType is DesignTimeType)
			{
				if (!(toType is RTTypeWrapper) && !(toType is DesignTimeType)) 
                {
#pragma warning suppress 56506 
                    ITypeProvider provider = fromType is RTTypeWrapper ? (fromType as RTTypeWrapper).Provider : (fromType as DesignTimeType).Provider; 
 					if (provider != null)
                        toType = provider.GetType(toType.FullName); 
				}
 			}
            else if (toType is RTTypeWrapper || toType is DesignTimeType)
            { 
                if (!(fromType is RTTypeWrapper) && !(fromType is DesignTimeType))
                { 
#pragma warning suppress 56506 
                    ITypeProvider provider = toType is RTTypeWrapper ? (toType as RTTypeWrapper).Provider : (toType as DesignTimeType).Provider;
                    if (provider != null) 
 						fromType = provider.GetType(fromType.FullName);
                }
            }
            else 
            {
                return toType.IsAssignableFrom(fromType); 
            } 

            //We need to check not null as there might be cases in which to and from types may not be found 
            if (toType == null || fromType == null)
                return false;

            if (equalBasedOnSameTypeRepresenting) 
            {
                if (IsRepresentingTheSameType(fromType, toType)) 
                    return true; 
            }
            else 
            {
                if (fromType == toType)
                    return true;
            } 

			if (TypeProvider.IsSubclassOf(fromType, toType)) 
 				return true; 

			if (toType.IsInterface == false) 
				return false;

			Type[] interfaces = fromType.GetInterfaces();
 
 			for (int i = 0; i < interfaces.Length; i++)
			{ 
 				// unfortunately, IsSubclassOf does not cover the case when they are the same type. 
 				if (interfaces[i] == toType)
					return true; 

 				if (TypeProvider.IsSubclassOf(interfaces[i], toType))
					return true;
			} 
			return false;
 		} 
        public static bool IsAssignable(Type toType, Type fromType) 
        {
            return IsAssignable(toType, fromType, false); 
        }
        public static bool IsSubclassOf(Type subclass, Type superClass)
		{
 			if (superClass == subclass) 
 				return false;
 
			if (subclass == null || superClass == null) 
 				return false;
 
            if (superClass == typeof(object))
                return true; // object is superclass of everything.

			subclass = subclass.BaseType; 
			while (subclass != null)
			{ 
 				if (superClass == subclass) 
					return true;
 
 				subclass = subclass.BaseType;
 			}
			return false;
 		} 
		public static bool IsEnum(Type type)
		{ 
			if (type == null) 
 				throw new ArgumentNullException("type");
 
			return TypeProvider.IsSubclassOf(type, typeof(Enum));
 		}
 		public static string[] GetEnumNames(Type enumType)
		{ 
 			if (enumType == null)
				throw new ArgumentNullException("enumType"); 
 
			if (!TypeProvider.IsSubclassOf(enumType, typeof(Enum)))
				throw new ArgumentException(TypeSystemSR.GetString("Error_TypeIsNotEnum")); 

 			FieldInfo[] flds = enumType.GetFields();

			List names = new List(); 
 			for (int i = 0; i < flds.Length; i++)
 				names.Add(flds[i].Name); 
 
			names.Sort();
 			return names.ToArray(); 


		}
		#endregion 

		#region Helper methods 
 
 		// This function could be re-entrant, so I have kept the flag to make it non-reentrant
		// I had one call stack in whcih ----eblyLoader.GetTypes() called ServiceProvider.GetService()for which 
 		// some one did Marshal.GetObjectForIUnknown() which caused the message pump to be executed
 		// which caused EnsureCurrentTypes to be called once again.
		private void EnsureCurrentTypes()
 		{ 
			if (this.executingEnsureCurrentTypes)
				return; 
 
			try
 			{ 
				bool hasTypeLoadErrors = false;
 				this.executingEnsureCurrentTypes = true;
 				if (this.addedAssemblies != null)
				{ 
 					// cache it to local variable
					string[] addedAssemblies2 = this.addedAssemblies.ToArray(); 
					this.addedAssemblies = null; 

					foreach (string path in addedAssemblies2) 
 					{
						AssemblyLoader loader = null;
 						try
 						{ 
							loader = new AssemblyLoader(this, path);
 							this.assemblyLoaders[path] = loader; 
						} 
						catch(Exception e)
						{ 
 							this.typeLoadErrors[path] = e;
							hasTypeLoadErrors = true;
 						}
 					} 
				}
 
 				if (this.addedCompileUnits != null) 
				{
					// cache it to local variable 
					CodeCompileUnit[] addedCompileUnits2 = this.addedCompileUnits.ToArray();
 					this.addedCompileUnits = null;

					foreach (CodeCompileUnit codeCompileUnit in addedCompileUnits2) 
 					{
 						CodeDomLoader loader = null; 
						try 
 						{
							loader = new CodeDomLoader(this, codeCompileUnit); 
							this.compileUnitLoaders[codeCompileUnit] = loader;
						}
 						catch (Exception e)
						{ 
 							// this will cause it to remove types
 							if (loader != null) 
								loader.Dispose(); 

 							this.typeLoadErrors[codeCompileUnit] = e; 
							hasTypeLoadErrors = true;
						}
					}
 				} 

				if (this.needRefreshCompileUnits != null) 
 				{ 
 					// cache it to local variable
					Dictionary needRefreshCompileUnits2 = new Dictionary(); 
 					foreach(KeyValuePair entry in this.needRefreshCompileUnits)
						needRefreshCompileUnits2.Add(entry.Key, entry.Value);
					this.needRefreshCompileUnits = null;
 
					foreach (KeyValuePair entry in needRefreshCompileUnits2)
 					{ 
						CodeDomLoader codeDomLoader = this.compileUnitLoaders[entry.Key] as CodeDomLoader; 

 						Debug.Assert(codeDomLoader != null, "How come we don't have CodeDOMLoader for the guy who needs refresh?"); 
 						if (codeDomLoader != null)
						{
 							try
							{ 
								codeDomLoader.Refresh(entry.Value);
							} 
 							catch(Exception e) 
							{
 								this.typeLoadErrors[entry.Value] = e; 
 								hasTypeLoadErrors = true;
							}
 						}
					} 
				}
 
				if (hasTypeLoadErrors) 
 				{
					if (this.TypeLoadErrorsChanged != null) 
 						FireEventsNoThrow(this.TypeLoadErrorsChanged, new object[] { this, EventArgs.Empty });
 				}
			}
 			finally 
			{
				this.executingEnsureCurrentTypes = false; 
			} 
 		}
 
		internal void AddType(Type type)
 		{
 			string typeName = type.FullName;
 
			if (!this.designTimeTypes.Contains(typeName))
 				this.designTimeTypes[typeName] = type; 
		} 

		internal void RemoveTypes(Type[] types) 
		{
 			foreach (Type type in types)
			{
 				string typeName = type.FullName; 
 				Debug.Assert(this.designTimeTypes.Contains(typeName), "How come you are removing type which you did not push in.");
 
				// collect all related cashed types (arrays, ref etc') to be deleted. 
 				// Note: we gather the names first as types might be dependant on each other.
				StringCollection removedTypeNames = new StringCollection(); 
				foreach (Type cachedtype in this.hashOfDTTypes.Values)
				{
 					Type elementType = cachedtype;
                    while (elementType != null && elementType.HasElementType) 
						elementType = elementType.GetElementType();
 
 					if (elementType == type) 
 						removedTypeNames.Add(cachedtype.FullName);
				} 
 				
				// remove cached types
				foreach (string hashedTypeName in removedTypeNames)
					this.hashOfDTTypes.Remove(hashedTypeName); 

 				// remove the type 
				this.designTimeTypes.Remove(typeName); 
 			}
 		} 

		private static void FireEventsNoThrow(Delegate eventDelegator, object[] args)
 		{
			if (eventDelegator != null) 
			{
				foreach (Delegate invokee in eventDelegator.GetInvocationList()) 
 				{ 
					try
 					{ 
 						invokee.DynamicInvoke(args);
					}
 					catch (Exception e)
					{ 
						Debug.Assert(false, "One of the event listener threw an Exception. \n" + e.ToString());
					} 
 				} 
			}
 		} 

 		private void RemoveCachedAssemblyWrappedTypes(Assembly assembly)
		{
 			ArrayList types = new ArrayList(this.hashOfRTTypes.Keys); 
			foreach (Type type in types)
			{ 
				if (type.IsGenericTypeDefinition) 
 					((RTTypeWrapper)this.hashOfRTTypes[type]).OnAssemblyRemoved(assembly);
				if (type.Assembly == assembly) 
 					this.hashOfRTTypes.Remove(type);
 			}
		}
 
 		#endregion
 
		#region IServiceProvider Members 

		public object GetService(Type serviceType) 
		{
 			if(this.serviceProvider == null)
				return null;
 
 			return this.serviceProvider.GetService(serviceType);
 		} 
 
		#endregion
 
 		#region IDisposable Members

		public void Dispose()
		{ 
			if (this.compileUnitLoaders != null)
 			{ 
				foreach (CodeDomLoader codeDomLoader in this.compileUnitLoaders.Values) 
 					codeDomLoader.Dispose();
 				this.compileUnitLoaders.Clear(); 
			}

 			this.addedAssemblies = null;
			this.addedCompileUnits = null; 
			this.needRefreshCompileUnits = null;
		} 
 
 		#endregion
	} 

 	internal class TypeSystemSR
 	{
		static TypeSystemSR loader = null; 
 		ResourceManager resources;
		internal TypeSystemSR() 
		{ 
			resources = new ResourceManager("System.Workflow.ComponentModel.Compiler.StringResources", Assembly.GetExecutingAssembly());
 		} 
		private static TypeSystemSR GetLoader()
 		{
 			if (loader == null)
				loader = new TypeSystemSR(); 

 			return loader; 
		} 
		private static CultureInfo Culture
		{ 
 			get { return null/*use ResourceManager default, CultureInfo.CurrentUICulture*/; }
		}
 		internal static string GetString(string name, params object[] args)
 		{ 
			return GetString(TypeSystemSR.Culture, name, args);
 		} 
		internal static string GetString(CultureInfo culture, string name, params object[] args) 
		{
			TypeSystemSR sys = GetLoader(); 

 			if (sys == null)
				return null;
 
 			string res = sys.resources.GetString(name, culture);
 
 			if (args != null && args.Length > 0) 
			{
 				return String.Format(CultureInfo.CurrentCulture, res, args); 
			}
			else
			{
 				return res; 
			}
 		} 
 		internal static string GetString(string name) 
		{
 			return GetString(TypeSystemSR.Culture, name); 
		}
		internal static string GetString(CultureInfo culture, string name)
		{
 			TypeSystemSR sys = GetLoader(); 

			if (sys == null) 
 				return null; 

 			return sys.resources.GetString(name, culture); 
		}
 	}
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
#pragma warning disable 1634, 1691 
namespace System.Workflow.ComponentModel.Compiler
{
 	using System;
	using System.CodeDom; 
	using System.Collections;
	using System.Collections.Specialized; 
 	using System.Collections.Generic; 
	using System.Diagnostics;
 	using System.Resources; 
 	using System.Reflection;
	using System.Globalization;
 	using System.IO;
    using System.Text.RegularExpressions; 

	public sealed class TypeProvider : ITypeProvider, IServiceProvider, IDisposable 
	{ 
		internal static readonly char[] nameSeparators = new char[]{'.', '+'};
 
 		private IServiceProvider	serviceProvider = null;

		private Hashtable designTimeTypes		= new Hashtable();
 		private Hashtable assemblyLoaders		= new Hashtable(); 
 		private Hashtable rawAssemblyLoaders	= new Hashtable();
		private Hashtable compileUnitLoaders	= new Hashtable(); 
        private Hashtable hashOfRTTypes         = new Hashtable(); 
 		private Hashtable hashOfDTTypes			= new Hashtable();
 
		// these variables will cache all the information which is passed to
		private List			addedAssemblies =  null;
		private List	addedCompileUnits = null;
 		private Dictionary needRefreshCompileUnits = null;				 
		private bool					executingEnsureCurrentTypes = false;
 		private Hashtable				typeLoadErrors = new Hashtable(); 
 		private Assembly				localAssembly = null; 

		public TypeProvider(IServiceProvider serviceProvider) 
 		{
			this.serviceProvider = serviceProvider;
		}
 
		#region Public methods
 
 		public void SetLocalAssembly(Assembly assembly) 
		{
 			this.localAssembly = assembly; 
 			if (this.TypesChanged != null)
				FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty });
 		}
 
		public void AddAssembly(Assembly assembly)
		{ 
			if (assembly == null) 
 				throw new ArgumentNullException("assembly");
 
			if (!rawAssemblyLoaders.Contains(assembly))
 			{
 				try
				{ 
 					rawAssemblyLoaders[assembly] = new AssemblyLoader(this, assembly, this.localAssembly == assembly);
					if (this.TypesChanged != null) 
						FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty }); 
				}
 				catch(Exception e) 
				{
 					this.typeLoadErrors[assembly.FullName] = e;
 					if (this.TypeLoadErrorsChanged != null)
						FireEventsNoThrow(this.TypeLoadErrorsChanged, new object[] { this, EventArgs.Empty }); 
 				}
			} 
		} 
		public void RemoveAssembly(Assembly assembly)
 		{ 
			if (assembly == null)
 				throw new ArgumentNullException("assembly");

 			AssemblyLoader assemblyLoader = (AssemblyLoader)this.rawAssemblyLoaders[assembly]; 
			if (assemblyLoader != null)
 			{ 
				this.rawAssemblyLoaders.Remove(assembly); 
				RemoveCachedAssemblyWrappedTypes(assembly);
 
				if (this.TypesChanged != null)
 					FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty });
			}
 		} 

 		public void AddAssemblyReference(string path) 
		{ 
 			if (path == null)
				throw new ArgumentNullException("path"); 

            if (File.Exists(path) &&
                !this.assemblyLoaders.ContainsKey(path) &&
				(this.addedAssemblies == null || !this.addedAssemblies.Contains(path))) 
			{
 				// lets put these changes into our cache 
				if (this.addedAssemblies == null) 
 					this.addedAssemblies = new List();
 				this.addedAssemblies.Add(path); 

				if (this.TypesChanged != null)
 					FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty });
			} 
		}
		public void RemoveAssemblyReference(string path) 
 		{ 
			if (path == null)
 				throw new ArgumentNullException("path"); 

 			AssemblyLoader assemblyLoader = this.assemblyLoaders[path] as AssemblyLoader;
			if (assemblyLoader != null)
 			{ 
				this.assemblyLoaders.Remove(path);
				RemoveCachedAssemblyWrappedTypes(assemblyLoader.Assembly); 
			} 

 			if (this.addedAssemblies != null && this.addedAssemblies.Contains(path)) 
				this.addedAssemblies.Remove(path);

 			if (this.typeLoadErrors.ContainsKey(path))
 			{ 
				this.typeLoadErrors.Remove(path);
 				if (this.TypeLoadErrorsChanged != null) 
					FireEventsNoThrow(this.TypeLoadErrorsChanged, new object[] { this, EventArgs.Empty }); 
			}
 
			if (this.TypesChanged != null)
 				FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty });
		}
 		public void AddCodeCompileUnit(CodeCompileUnit codeCompileUnit) 
 		{
			if (codeCompileUnit == null) 
 				throw new ArgumentNullException("codeCompileUnit"); 

			if (this.compileUnitLoaders.ContainsKey(codeCompileUnit) || (this.addedCompileUnits != null && this.addedCompileUnits.Contains(codeCompileUnit))) 
				throw new ArgumentException(TypeSystemSR.GetString("Error_DuplicateCodeCompileUnit"), "codeCompileUnit");

			// lets put these changes into our cache
 			if (this.addedCompileUnits == null) 
				this.addedCompileUnits = new List();
 			this.addedCompileUnits.Add(codeCompileUnit); 
 			if (this.needRefreshCompileUnits != null && this.needRefreshCompileUnits.ContainsKey(codeCompileUnit)) 
				this.needRefreshCompileUnits.Remove(codeCompileUnit);
 
 			if (this.TypesChanged != null)
				FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty });
		}
		public void RemoveCodeCompileUnit(CodeCompileUnit codeCompileUnit) 
 		{
			if (codeCompileUnit == null) 
 				throw new ArgumentNullException("codeCompileUnit"); 

 			// lets put these changes into our cache 
			CodeDomLoader codeDomLoader = this.compileUnitLoaders[codeCompileUnit] as CodeDomLoader;
 			if (codeDomLoader != null)
			{
				codeDomLoader.Dispose(); 
				this.compileUnitLoaders.Remove(codeCompileUnit);
 			} 
 
			if (this.addedCompileUnits != null && this.addedCompileUnits.Contains(codeCompileUnit))
 				this.addedCompileUnits.Remove(codeCompileUnit); 
 			if (this.needRefreshCompileUnits != null && this.needRefreshCompileUnits.ContainsKey(codeCompileUnit))
				this.needRefreshCompileUnits.Remove(codeCompileUnit);

 			if (this.typeLoadErrors.ContainsKey(codeCompileUnit)) 
			{
				this.typeLoadErrors.Remove(codeCompileUnit); 
				if (this.TypeLoadErrorsChanged != null) 
 					FireEventsNoThrow(this.TypeLoadErrorsChanged, new object[] { this, EventArgs.Empty });
			} 

 			if (this.TypesChanged != null)
 				FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty });
		} 
 		public void RefreshCodeCompileUnit(CodeCompileUnit codeCompileUnit, EventHandler refresher)
		{ 
			if (codeCompileUnit == null) 
				throw new ArgumentNullException("codeCompileUnit");
 
 			if (!this.compileUnitLoaders.Contains(codeCompileUnit) && (this.addedCompileUnits != null && !this.addedCompileUnits.Contains(codeCompileUnit)))
				throw new ArgumentException(TypeSystemSR.GetString("Error_NoCodeCompileUnit"), "codeCompileUnit");

 			if (this.needRefreshCompileUnits == null) 
 				this.needRefreshCompileUnits = new Dictionary();
			this.needRefreshCompileUnits[codeCompileUnit] = refresher; 
 
 			if (this.TypesChanged != null)
				FireEventsNoThrow(this.TypesChanged, new object[] { this, EventArgs.Empty }); 
		}
        #endregion

        #region TargetFrameworkProvider Support 
        //
        // In general this func can be used by anyone that wants to configure TypeProvder 
        // to do non standard type to assembly name mapping 
        // Specifically this func is set by Microsoft.Workflow.VSDesigner when running within VS
        // The func encapsulates VS multi-targeting functionality so that System.Workflow.ComponentModel 
        // does not need to take a dependency on VS bits.
        public Func AssemblyNameResolver
        {
            get; 
            set;
        } 
        public Func IsSupportedPropertyResolver 
        {
            get; 
            set;
        }
        //
        // VS multi-targeting uses LMR which, unlike reflection, does not cache 
        // Caching in the caller (here) is critical for performance
        // GetAssemblyName, IsSupportedProperty provide both default behavior 
        // if *Resolver is null and a cache over the LMR methods behind the Resolvers 
        // Caches rely on a single Type universe and object equality however due to issues in reflection it is
        // possible to get redundant items in the cache.  This is because reflection may return different instances 
        // of PropertyInfo depending on what API is called.  This is rare but it can happen.  Worst case is
        // redundant entries in the cache; this will not cause incorrect behavior.
        Dictionary typeToAssemblyName = null;
        Dictionary supportedProperties = null; 

        public string GetAssemblyName(Type type) 
        { 
            if (type == null)
            { 
                throw new ArgumentNullException("type");
            }

            if (typeToAssemblyName == null) 
            {
                typeToAssemblyName = new Dictionary(); 
            } 

            string assemblyName = null; 
            if (!typeToAssemblyName.TryGetValue(type, out assemblyName))
            {
                //
                // DesignTimeType will not have an assembly 
                if (type.Assembly != null)
                { 
                    if (this.AssemblyNameResolver != null) 
                    {
                        assemblyName = this.AssemblyNameResolver(type); 
                    }
                    else
                    {
                        assemblyName = type.Assembly.FullName; 
                    }
                    typeToAssemblyName.Add(type, assemblyName); 
                } 
            }
 
            if (assemblyName == null)
            {
                assemblyName = string.Empty;
            } 

            return assemblyName; 
        } 

        public bool IsSupportedProperty(PropertyInfo property, object declaringInstance) 
        {
            if (property == null)
            {
                throw new ArgumentNullException("property"); 
            }
            if (declaringInstance == null) 
            { 
                throw new ArgumentNullException("declaringInstance");
            } 
            //
            // If we don't have a resolver to determine if a property is supported
            // just return true
            if (IsSupportedPropertyResolver == null) 
            {
                return true; 
            } 

            if (supportedProperties == null) 
            {
                supportedProperties = new Dictionary();
            }
 
            bool supported = false;
            if (!supportedProperties.TryGetValue(property, out supported)) 
            { 
                supported = IsSupportedPropertyResolver(property, declaringInstance);
                supportedProperties.Add(property, supported); 
            }

            return supported;
        } 

        #endregion 
 
        #region ITypeProvider Members
 
        public Type GetType(string name)
		{
 			if (name == null)
				throw new ArgumentNullException("name"); 

 			return GetType(name, false); 
 		} 

		public Type GetType(string name, bool throwOnError) 
 		{
			if (name == null)
				throw new ArgumentNullException("name");
 
			EnsureCurrentTypes();
 			 
			bool hasTypeLoadErrors = false; 
 			Type returnType = null;
            string typeName = string.Empty; 
            string[] parameters = null;
 			string elementDecorator = string.Empty;

			if (ParseHelpers.ParseTypeName(name, ParseHelpers.ParseTypeNameLanguage.NetFramework, out typeName, out parameters, out elementDecorator)) 
 			{
                if ((parameters != null) && (parameters.Length > 0)) 
                { 
					//Generic type
                    Type templateType = GetType(typeName, throwOnError); 
                    if ((templateType == null) || (!templateType.IsGenericTypeDefinition))
                        return null;
                    Type[] templateParamTypes = new Type[parameters.Length];
                    for(int index = 0; index < parameters.Length; index++) 
                    {
                        Type templateParameter = GetType(parameters[index], throwOnError); 
                        if (templateParameter == null) 
                            return null;
                        templateParamTypes[index] = templateParameter; 
                    }
					return templateType.MakeGenericType(templateParamTypes);
                }
				else if (elementDecorator != string.Empty) 
 				{
					//type with element (Array, ByRef, Pointer) 
 					Type elementType = this.GetType(typeName); 
 					if (elementType != null)
					{ 
 						// first we verify the name is formated well (AssemblyQualifiedName for generic
						// parameters + no spaces in array brackets)
						System.Text.StringBuilder nameBuilder = new System.Text.StringBuilder(elementType.FullName);
						for (int loop = 0; loop < elementDecorator.Length; loop++) 
 							if (elementDecorator[loop] != ' ')
								nameBuilder.Append(elementDecorator[loop]); 
 
 						name = nameBuilder.ToString();
 
 						// let tha assembly of the element type a chance to find a type (will fail only
						// if element contains parameter from external assembly
 						if (elementType.Assembly != null)
							returnType = elementType.Assembly.GetType(name, false); 

						if (returnType == null) 
						{ 
 							// now we can fetch or create the type
							if (this.hashOfDTTypes.Contains(name)) 
 							{
 								returnType = this.hashOfDTTypes[name] as Type;
							}
 							else 
							{
								returnType = new DesignTimeType(null, name, this); 
								this.hashOfDTTypes.Add(name, returnType); 
 							}
                            return returnType; 
						}
 					}
 				}
				else 
 				{
					// regular type, get the type name 
					string assemblyName = string.Empty; 
					int indexOfComma = name.IndexOf(',');
 					if (indexOfComma != -1) 
					{
 						typeName = name.Substring(0, indexOfComma);
 						assemblyName = name.Substring(indexOfComma + 1).Trim();
					} 
 					typeName = typeName.Trim();
					if (typeName.Length > 0) 
					{ 
						returnType = this.designTimeTypes[typeName] as Type;
 						if (returnType == null) 
						{
 							foreach (DictionaryEntry dictionaryEntry in this.rawAssemblyLoaders)
 							{
								AssemblyLoader assemblyLoader = dictionaryEntry.Value as AssemblyLoader; 
 								if ((assemblyName.Length == 0) || (ParseHelpers.AssemblyNameEquals(assemblyLoader.AssemblyName, assemblyName)))
								{ 
									try 
									{
 										returnType = assemblyLoader.GetType(typeName); 
									}
 									catch (Exception e)
 									{
										if (!this.typeLoadErrors.Contains(dictionaryEntry.Key)) 
 										{
											this.typeLoadErrors[dictionaryEntry.Key] = e; 
											hasTypeLoadErrors = true; 
										}
 										// bubble up exceptions only when appropiate 
										if (throwOnError)
 											throw e;
 									}
									if (returnType != null) 
 										break;
								} 
							} 
						}
 						 
						if (returnType == null)
 						{
 							foreach (DictionaryEntry dictionaryEntry in this.assemblyLoaders)
							{ 
 								AssemblyLoader assemblyLoader = dictionaryEntry.Value as AssemblyLoader;
								if ((assemblyName.Length == 0) || (ParseHelpers.AssemblyNameEquals(assemblyLoader.AssemblyName, assemblyName))) 
								{ 
									try
 									{ 
										returnType = assemblyLoader.GetType(typeName);
 									}
 									catch (Exception e)
									{ 
 										if (!this.typeLoadErrors.Contains(dictionaryEntry.Key))
										{ 
											this.typeLoadErrors[dictionaryEntry.Key] = e; 
											hasTypeLoadErrors = true;
 										} 
										// bubble up exceptions only when appropiate
 										if (throwOnError)
 											throw e;
									} 
 									if (returnType != null)
										break; 
								} 
							}
 						} 

						if (hasTypeLoadErrors)
 						{
 							if (this.TypeLoadErrorsChanged != null) 
								FireEventsNoThrow(this.TypeLoadErrorsChanged, new object[] { this, EventArgs.Empty });
 						} 
 
						if (returnType == null && this.localAssembly != null && assemblyName == this.localAssembly.FullName)
							returnType = this.localAssembly.GetType(typeName); 
					}
 				}
			}
 
            if (returnType == null)
            { 
                if(throwOnError) 
                    throw new Exception(TypeSystemSR.GetString(CultureInfo.CurrentCulture, "Error_TypeResolution", name));
                else 
                    return null;
            }

            // replace the System.Type with RTTypeWrapper for generic types. 
            // WinOE Bug 16560: The type provider may be used at runtime.  No RTTypeWrapper should ever be returned
            // at runtime. 
            // At design time, we need to wrap all generic types even if the parameter types are not 
            // design time types.  This is because our parsing function creates a base generic type before it binds
            // all the parameters.  The RTTypeWrapper.MakeGenericType override will then take care of binding to 
            // design time types.
            if (this.designTimeTypes != null && this.designTimeTypes.Count > 0 && returnType.Assembly != null && returnType.IsGenericTypeDefinition)
            {
                if (this.hashOfRTTypes.Contains(returnType)) 
                {
                    returnType = (Type)this.hashOfRTTypes[returnType]; 
                } 
                else
                { 
                    Type returnType2 = new RTTypeWrapper(this, returnType);
                    this.hashOfRTTypes.Add(returnType, returnType2);
                    returnType = returnType2;
                } 
            }
            return returnType; 
 		} 

 		public Type[] GetTypes() 
		{
 			EnsureCurrentTypes();

			bool hasTypeLoadErrors = false; 
			this.typeLoadErrors.Clear();//clear all old errors
 
			List typeList = new List(); 

 			// Design time types 
			foreach (Type type in this.designTimeTypes.Values)
 					typeList.Add(type);

 			foreach (DictionaryEntry dictionaryEntry in this.assemblyLoaders) 
			{
 				AssemblyLoader assemblyLoader = dictionaryEntry.Value as AssemblyLoader; 
				try 
				{
					typeList.AddRange(assemblyLoader.GetTypes()); 
 				}
				catch (Exception e)
 				{
 					ReflectionTypeLoadException typeLoadException = e as ReflectionTypeLoadException; 
					if (typeLoadException != null)
 					{ 
						//we should at least add the types that did get loaded 
						foreach (Type type in typeLoadException.Types)
						{ 
 							if (type != null)
								typeList.Add(type);
 						}
 					} 

					//we should have the latest exception for every assembly (user might have copied required dlls over) 
 					if (this.typeLoadErrors.Contains(dictionaryEntry.Key)) 
						this.typeLoadErrors.Remove(dictionaryEntry.Key);
 
					this.typeLoadErrors[dictionaryEntry.Key] = e;
					hasTypeLoadErrors = true;
 				}
			} 

 			foreach (DictionaryEntry dictionaryEntry in this.rawAssemblyLoaders) 
 			{ 
				AssemblyLoader assemblyLoader = dictionaryEntry.Value as AssemblyLoader;
 				try 
				{
					typeList.AddRange(assemblyLoader.GetTypes());
				}
 				catch (Exception e) 
				{
 					ReflectionTypeLoadException typeLoadException = e as ReflectionTypeLoadException; 
 					if (typeLoadException != null) 
					{
 						//we should at least add the types that did get loaded 
						foreach (Type type in typeLoadException.Types)
						{
							if (type != null)
 								typeList.Add(type); 
						}
 					} 
 					//we should have the latest exception for every assembly (user might have copied required dlls over) 
					if (this.typeLoadErrors.Contains(dictionaryEntry.Key))
 						this.typeLoadErrors.Remove(dictionaryEntry.Key); 

					this.typeLoadErrors[dictionaryEntry.Key] = e;
					hasTypeLoadErrors = true;
				} 
 			}
 
			if (hasTypeLoadErrors) 
 			{
 				if (this.TypeLoadErrorsChanged != null) 
					FireEventsNoThrow(this.TypeLoadErrorsChanged, new object[] { this, EventArgs.Empty });
 			}

			return typeList.ToArray(); 
		}
 
		public IDictionary TypeLoadErrors 
 		{
			get 
 			{
 				Dictionary collection = new Dictionary();

				foreach (DictionaryEntry entry in this.typeLoadErrors) 
 				{
					Exception e = entry.Value as Exception; 
					while (e is TargetInvocationException) 
						e = e.InnerException;
 
 					if (e != null)
					{
 						string typeLoadError = null;
 
 						if (entry.Key is CodeCompileUnit)
							typeLoadError = TypeSystemSR.GetString("Error_CodeCompileUnitNotLoaded", new object[] { e.Message }); 
 						else if (entry.Key is String) 
							typeLoadError = TypeSystemSR.GetString("Error_AssemblyRefNotLoaded", new object[] { entry.Key.ToString(), e.Message });
 
						//wrap the original exception with a new one with a custom error message
						if (typeLoadError != null)
 							e = new Exception(typeLoadError, e);
 
						collection.Add(entry.Key, e);
 					} 
 				} 

				return collection; 
 			}
		}

		public Assembly LocalAssembly 
		{
 			get 
			{ 
 				return this.localAssembly;
 			} 
		}
 		public event EventHandler TypeLoadErrorsChanged;
		public event EventHandler TypesChanged;
 
        public ICollection ReferencedAssemblies
        { 
            get 
            {
                EnsureCurrentTypes(); 

                List referencedAssemblies = new List();
                foreach (AssemblyLoader loader in this.assemblyLoaders.Values)
                { 
                    if (loader.Assembly != null)
                        referencedAssemblies.Add(loader.Assembly); 
                } 

                foreach (Assembly assembly in this.rawAssemblyLoaders.Keys) 
                    referencedAssemblies.Add(assembly);

                return referencedAssemblies.AsReadOnly();
            } 
        }
 
		#endregion 

		#region TypeProvider Static Methods 

 		public static Type GetEventHandlerType(EventInfo eventInfo)
		{
 			if (eventInfo == null) 
 				throw new ArgumentNullException("eventInfo");
 
			MethodInfo m = eventInfo.GetAddMethod(true); 
            if (m != null)
            { 
                ParameterInfo[] p = m.GetParameters();
                Type del = typeof(Delegate);
                for (int i = 0; i < p.Length; i++)
                { 
                    Type c = p[i].ParameterType;
                    if (TypeProvider.IsSubclassOf(c, del)) 
                        return c; 
                }
            } 
 			return null;
		}

        internal static bool IsRepresentingTheSameType(Type firstType, Type secondType) 
        {
            if (firstType == null || secondType == null) 
                return false; 

            if (firstType == secondType) 
                return true;

            if (firstType.FullName != secondType.FullName)
                return false; 

            if (firstType.Assembly != secondType.Assembly) 
                return false; 

            if (firstType.Assembly != null) 
                if (firstType.AssemblyQualifiedName != secondType.AssemblyQualifiedName)
                    return false;

            return true; 
        }
 
		internal static bool IsAssignable(Type toType, Type fromType,bool equalBasedOnSameTypeRepresenting) 
		{
 			if (toType == null || fromType == null) 
				return false;

            if (equalBasedOnSameTypeRepresenting)
            { 
                if (IsRepresentingTheSameType(fromType, toType))
                    return true; 
            } 
            else
            { 
                if (fromType == toType)
                    return true;
            }
 
 			if (toType.IsGenericTypeDefinition)
 				return toType.IsAssignableFrom(fromType); 
 
			// runtime type can never be assigned to design time type
 			if (toType.Assembly == null && fromType.Assembly != null) 
				return false;
            if (fromType is RTTypeWrapper || fromType is DesignTimeType)
			{
				if (!(toType is RTTypeWrapper) && !(toType is DesignTimeType)) 
                {
#pragma warning suppress 56506 
                    ITypeProvider provider = fromType is RTTypeWrapper ? (fromType as RTTypeWrapper).Provider : (fromType as DesignTimeType).Provider; 
 					if (provider != null)
                        toType = provider.GetType(toType.FullName); 
				}
 			}
            else if (toType is RTTypeWrapper || toType is DesignTimeType)
            { 
                if (!(fromType is RTTypeWrapper) && !(fromType is DesignTimeType))
                { 
#pragma warning suppress 56506 
                    ITypeProvider provider = toType is RTTypeWrapper ? (toType as RTTypeWrapper).Provider : (toType as DesignTimeType).Provider;
                    if (provider != null) 
 						fromType = provider.GetType(fromType.FullName);
                }
            }
            else 
            {
                return toType.IsAssignableFrom(fromType); 
            } 

            //We need to check not null as there might be cases in which to and from types may not be found 
            if (toType == null || fromType == null)
                return false;

            if (equalBasedOnSameTypeRepresenting) 
            {
                if (IsRepresentingTheSameType(fromType, toType)) 
                    return true; 
            }
            else 
            {
                if (fromType == toType)
                    return true;
            } 

			if (TypeProvider.IsSubclassOf(fromType, toType)) 
 				return true; 

			if (toType.IsInterface == false) 
				return false;

			Type[] interfaces = fromType.GetInterfaces();
 
 			for (int i = 0; i < interfaces.Length; i++)
			{ 
 				// unfortunately, IsSubclassOf does not cover the case when they are the same type. 
 				if (interfaces[i] == toType)
					return true; 

 				if (TypeProvider.IsSubclassOf(interfaces[i], toType))
					return true;
			} 
			return false;
 		} 
        public static bool IsAssignable(Type toType, Type fromType) 
        {
            return IsAssignable(toType, fromType, false); 
        }
        public static bool IsSubclassOf(Type subclass, Type superClass)
		{
 			if (superClass == subclass) 
 				return false;
 
			if (subclass == null || superClass == null) 
 				return false;
 
            if (superClass == typeof(object))
                return true; // object is superclass of everything.

			subclass = subclass.BaseType; 
			while (subclass != null)
			{ 
 				if (superClass == subclass) 
					return true;
 
 				subclass = subclass.BaseType;
 			}
			return false;
 		} 
		public static bool IsEnum(Type type)
		{ 
			if (type == null) 
 				throw new ArgumentNullException("type");
 
			return TypeProvider.IsSubclassOf(type, typeof(Enum));
 		}
 		public static string[] GetEnumNames(Type enumType)
		{ 
 			if (enumType == null)
				throw new ArgumentNullException("enumType"); 
 
			if (!TypeProvider.IsSubclassOf(enumType, typeof(Enum)))
				throw new ArgumentException(TypeSystemSR.GetString("Error_TypeIsNotEnum")); 

 			FieldInfo[] flds = enumType.GetFields();

			List names = new List(); 
 			for (int i = 0; i < flds.Length; i++)
 				names.Add(flds[i].Name); 
 
			names.Sort();
 			return names.ToArray(); 


		}
		#endregion 

		#region Helper methods 
 
 		// This function could be re-entrant, so I have kept the flag to make it non-reentrant
		// I had one call stack in whcih ----eblyLoader.GetTypes() called ServiceProvider.GetService()for which 
 		// some one did Marshal.GetObjectForIUnknown() which caused the message pump to be executed
 		// which caused EnsureCurrentTypes to be called once again.
		private void EnsureCurrentTypes()
 		{ 
			if (this.executingEnsureCurrentTypes)
				return; 
 
			try
 			{ 
				bool hasTypeLoadErrors = false;
 				this.executingEnsureCurrentTypes = true;
 				if (this.addedAssemblies != null)
				{ 
 					// cache it to local variable
					string[] addedAssemblies2 = this.addedAssemblies.ToArray(); 
					this.addedAssemblies = null; 

					foreach (string path in addedAssemblies2) 
 					{
						AssemblyLoader loader = null;
 						try
 						{ 
							loader = new AssemblyLoader(this, path);
 							this.assemblyLoaders[path] = loader; 
						} 
						catch(Exception e)
						{ 
 							this.typeLoadErrors[path] = e;
							hasTypeLoadErrors = true;
 						}
 					} 
				}
 
 				if (this.addedCompileUnits != null) 
				{
					// cache it to local variable 
					CodeCompileUnit[] addedCompileUnits2 = this.addedCompileUnits.ToArray();
 					this.addedCompileUnits = null;

					foreach (CodeCompileUnit codeCompileUnit in addedCompileUnits2) 
 					{
 						CodeDomLoader loader = null; 
						try 
 						{
							loader = new CodeDomLoader(this, codeCompileUnit); 
							this.compileUnitLoaders[codeCompileUnit] = loader;
						}
 						catch (Exception e)
						{ 
 							// this will cause it to remove types
 							if (loader != null) 
								loader.Dispose(); 

 							this.typeLoadErrors[codeCompileUnit] = e; 
							hasTypeLoadErrors = true;
						}
					}
 				} 

				if (this.needRefreshCompileUnits != null) 
 				{ 
 					// cache it to local variable
					Dictionary needRefreshCompileUnits2 = new Dictionary(); 
 					foreach(KeyValuePair entry in this.needRefreshCompileUnits)
						needRefreshCompileUnits2.Add(entry.Key, entry.Value);
					this.needRefreshCompileUnits = null;
 
					foreach (KeyValuePair entry in needRefreshCompileUnits2)
 					{ 
						CodeDomLoader codeDomLoader = this.compileUnitLoaders[entry.Key] as CodeDomLoader; 

 						Debug.Assert(codeDomLoader != null, "How come we don't have CodeDOMLoader for the guy who needs refresh?"); 
 						if (codeDomLoader != null)
						{
 							try
							{ 
								codeDomLoader.Refresh(entry.Value);
							} 
 							catch(Exception e) 
							{
 								this.typeLoadErrors[entry.Value] = e; 
 								hasTypeLoadErrors = true;
							}
 						}
					} 
				}
 
				if (hasTypeLoadErrors) 
 				{
					if (this.TypeLoadErrorsChanged != null) 
 						FireEventsNoThrow(this.TypeLoadErrorsChanged, new object[] { this, EventArgs.Empty });
 				}
			}
 			finally 
			{
				this.executingEnsureCurrentTypes = false; 
			} 
 		}
 
		internal void AddType(Type type)
 		{
 			string typeName = type.FullName;
 
			if (!this.designTimeTypes.Contains(typeName))
 				this.designTimeTypes[typeName] = type; 
		} 

		internal void RemoveTypes(Type[] types) 
		{
 			foreach (Type type in types)
			{
 				string typeName = type.FullName; 
 				Debug.Assert(this.designTimeTypes.Contains(typeName), "How come you are removing type which you did not push in.");
 
				// collect all related cashed types (arrays, ref etc') to be deleted. 
 				// Note: we gather the names first as types might be dependant on each other.
				StringCollection removedTypeNames = new StringCollection(); 
				foreach (Type cachedtype in this.hashOfDTTypes.Values)
				{
 					Type elementType = cachedtype;
                    while (elementType != null && elementType.HasElementType) 
						elementType = elementType.GetElementType();
 
 					if (elementType == type) 
 						removedTypeNames.Add(cachedtype.FullName);
				} 
 				
				// remove cached types
				foreach (string hashedTypeName in removedTypeNames)
					this.hashOfDTTypes.Remove(hashedTypeName); 

 				// remove the type 
				this.designTimeTypes.Remove(typeName); 
 			}
 		} 

		private static void FireEventsNoThrow(Delegate eventDelegator, object[] args)
 		{
			if (eventDelegator != null) 
			{
				foreach (Delegate invokee in eventDelegator.GetInvocationList()) 
 				{ 
					try
 					{ 
 						invokee.DynamicInvoke(args);
					}
 					catch (Exception e)
					{ 
						Debug.Assert(false, "One of the event listener threw an Exception. \n" + e.ToString());
					} 
 				} 
			}
 		} 

 		private void RemoveCachedAssemblyWrappedTypes(Assembly assembly)
		{
 			ArrayList types = new ArrayList(this.hashOfRTTypes.Keys); 
			foreach (Type type in types)
			{ 
				if (type.IsGenericTypeDefinition) 
 					((RTTypeWrapper)this.hashOfRTTypes[type]).OnAssemblyRemoved(assembly);
				if (type.Assembly == assembly) 
 					this.hashOfRTTypes.Remove(type);
 			}
		}
 
 		#endregion
 
		#region IServiceProvider Members 

		public object GetService(Type serviceType) 
		{
 			if(this.serviceProvider == null)
				return null;
 
 			return this.serviceProvider.GetService(serviceType);
 		} 
 
		#endregion
 
 		#region IDisposable Members

		public void Dispose()
		{ 
			if (this.compileUnitLoaders != null)
 			{ 
				foreach (CodeDomLoader codeDomLoader in this.compileUnitLoaders.Values) 
 					codeDomLoader.Dispose();
 				this.compileUnitLoaders.Clear(); 
			}

 			this.addedAssemblies = null;
			this.addedCompileUnits = null; 
			this.needRefreshCompileUnits = null;
		} 
 
 		#endregion
	} 

 	internal class TypeSystemSR
 	{
		static TypeSystemSR loader = null; 
 		ResourceManager resources;
		internal TypeSystemSR() 
		{ 
			resources = new ResourceManager("System.Workflow.ComponentModel.Compiler.StringResources", Assembly.GetExecutingAssembly());
 		} 
		private static TypeSystemSR GetLoader()
 		{
 			if (loader == null)
				loader = new TypeSystemSR(); 

 			return loader; 
		} 
		private static CultureInfo Culture
		{ 
 			get { return null/*use ResourceManager default, CultureInfo.CurrentUICulture*/; }
		}
 		internal static string GetString(string name, params object[] args)
 		{ 
			return GetString(TypeSystemSR.Culture, name, args);
 		} 
		internal static string GetString(CultureInfo culture, string name, params object[] args) 
		{
			TypeSystemSR sys = GetLoader(); 

 			if (sys == null)
				return null;
 
 			string res = sys.resources.GetString(name, culture);
 
 			if (args != null && args.Length > 0) 
			{
 				return String.Format(CultureInfo.CurrentCulture, res, args); 
			}
			else
			{
 				return res; 
			}
 		} 
 		internal static string GetString(string name) 
		{
 			return GetString(TypeSystemSR.Culture, name); 
		}
		internal static string GetString(CultureInfo culture, string name)
		{
 			TypeSystemSR sys = GetLoader(); 

			if (sys == null) 
 				return null; 

 			return sys.resources.GetString(name, culture); 
		}
 	}
}

// 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