|
#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;
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
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<string> addedAssemblies = null;
private List<CodeCompileUnit> addedCompileUnits = null;
private Dictionary<CodeCompileUnit, EventHandler> 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<string>();
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<CodeCompileUnit>();
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<CodeCompileUnit, EventHandler>();
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<Type, string> AssemblyNameResolver
{
get;
set;
}
public Func<PropertyInfo, object, bool> 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<Type, string> typeToAssemblyName = null;
Dictionary<PropertyInfo, bool> supportedProperties = null;
public string GetAssemblyName(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
if (typeToAssemblyName == null)
{
typeToAssemblyName = new Dictionary<Type, string>();
}
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<PropertyInfo, bool>();
}
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<Type> typeList = new List<Type>();
// 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<object, Exception> TypeLoadErrors
{
get
{
Dictionary<object, Exception> collection = new Dictionary<object, Exception>();
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<Assembly> ReferencedAssemblies
{
get
{
EnsureCurrentTypes();
List<Assembly> referencedAssemblies = new List<Assembly>();
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<string> names = new List<String>();
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<CodeCompileUnit, EventHandler> needRefreshCompileUnits2 = new Dictionary<CodeCompileUnit, EventHandler>();
foreach (KeyValuePair<CodeCompileUnit, EventHandler> entry in this.needRefreshCompileUnits)
needRefreshCompileUnits2.Add(entry.Key, entry.Value);
this.needRefreshCompileUnits = null;
foreach (KeyValuePair<CodeCompileUnit, EventHandler> 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);
}
}
}
|