/// <summary> /// Binds a name to type. /// </summary> /// <param name="typeName">The name of the type to bind.</param> /// <param name="debugContext">The debug context to log to.</param> /// <returns> /// The type that the name has been bound to, or null if the type could not be resolved. /// </returns> /// <exception cref="System.ArgumentNullException">The typeName argument is null.</exception> public override Type BindToType(string typeName, DebugContext debugContext = null) { if (typeName == null) { throw new ArgumentNullException("typeName"); } Type result; lock (NAMETOTYPE_LOCK) { if (typeMap.TryGetValue(typeName, out result) == false) { result = this.ParseTypeName(typeName, debugContext); if (result == null && debugContext != null) { debugContext.LogWarning("Failed deserialization type lookup for type name '" + typeName + "'."); } // We allow null values on purpose so we don't have to keep re-performing invalid name lookups typeMap.Add(typeName, result); } } return(result); }
/// <summary> /// Binds a name to type. /// </summary> /// <param name="typeName">The name of the type to bind.</param> /// <param name="debugContext">The debug context to log to.</param> /// <returns> /// The type that the name has been bound to, or null if the type could not be resolved. /// </returns> /// <exception cref="System.ArgumentNullException">The typeName argument is null.</exception> public override Type BindToType(string typeName, DebugContext debugContext = null) { if (typeName == null) { throw new ArgumentNullException("typeName"); } Type result; lock (TYPEMAP_LOCK) { if (typeMap.TryGetValue(typeName, out result) == false) { // Looks for custom defined type name lookups defined with the BindTypeNameToTypeAttribute. customTypeNameToTypeBindings.TryGetValue(typeName, out result); // Do more fancy stuff. // Final fallback to classic .NET type string format if (result == null) { result = Type.GetType(typeName); } if (result == null) { result = AssemblyUtilities.GetTypeByCachedFullName(typeName); } // TODO: Type lookup error handling; use an out bool or a "Try" pattern? string typeStr, assemblyStr; ParseName(typeName, out typeStr, out assemblyStr); if (result == null && assemblyStr != null && assemblyNameLookUp.ContainsKey(assemblyStr)) { var assembly = assemblyNameLookUp[assemblyStr]; result = assembly.GetType(typeStr); } if (result == null) { result = AssemblyUtilities.GetTypeByCachedFullName(typeStr); } if (result == null && debugContext != null) { debugContext.LogWarning("Failed deserialization type lookup for type name '" + typeName + "'."); } // We allow null values on purpose so we don't have to keep re-performing invalid name lookups typeMap.Add(typeName, result); } } return(result); }
/// <summary> /// Bind a type to a name. /// </summary> /// <param name="type">The type to bind.</param> /// <param name="debugContext">The debug context to log to.</param> /// <returns> /// The name that the type has been bound to. /// </returns> /// <exception cref="System.ArgumentNullException">The type argument is null.</exception> public override string BindToName(Type type, DebugContext debugContext = null) { if (type == null) { throw new ArgumentNullException("type"); } string result; lock (TYPETONAME_LOCK) { if (nameMap.TryGetValue(type, out result) == false) { if (type.IsGenericType) { // We track down all assemblies in the generic type definition List <Type> toResolve = type.GetGenericArguments().ToList(); HashSet <Assembly> assemblies = new HashSet <Assembly>(); while (toResolve.Count > 0) { var t = toResolve[0]; if (t.IsGenericType) { toResolve.AddRange(t.GetGenericArguments()); } assemblies.Add(t.Assembly); toResolve.RemoveAt(0); } result = type.FullName + ", " + type.Assembly.GetName().Name; foreach (var ass in assemblies) { result = result.Replace(ass.FullName, ass.GetName().Name); } } else if (type.IsDefined(typeof(CompilerGeneratedAttribute), false)) { result = type.FullName + ", " + type.Assembly.GetName().Name; } else { result = type.FullName + ", " + type.Assembly.GetName().Name; } nameMap.Add(type, result); } } return(result); }
private Type ParseTypeName(string typeName, DebugContext debugContext) { Type type; // Look for custom defined type name lookups defined with the BindTypeNameToTypeAttribute. if (customTypeNameToTypeBindings.TryGetValue(typeName, out type)) { return(type); } // Let's try it the traditional .NET way type = Type.GetType(typeName); if (type != null) { return(type); } // Let's try a short-cut type = AssemblyUtilities.GetTypeByCachedFullName(typeName); if (type != null) { return(type); } // Generic/array type name handling type = ParseGenericAndOrArrayType(typeName, debugContext); if (type != null) { return(type); } string typeStr, assemblyStr; ParseName(typeName, out typeStr, out assemblyStr); if (assemblyStr != null && assemblyNameLookUp.ContainsKey(assemblyStr)) { var assembly = assemblyNameLookUp[assemblyStr]; type = assembly.GetType(typeStr); if (type != null) { return(type); } } type = AssemblyUtilities.GetTypeByCachedFullName(typeStr); if (type != null) { return(type); } return(null); }
private Type ParseGenericAndOrArrayType(string typeName, DebugContext debugContext) { string actualTypeName; List <string> genericArgNames; bool isGeneric; bool isArray; int arrayRank; if (!TryParseGenericAndOrArrayTypeName(typeName, out actualTypeName, out isGeneric, out genericArgNames, out isArray, out arrayRank)) { return(null); } Type type = this.BindToType(actualTypeName, debugContext); if (type == null) { return(null); } if (isGeneric) { if (!type.IsGenericType) { return(null); } List <Type> args = genericArgTypesList; args.Clear(); for (int i = 0; i < genericArgNames.Count; i++) { Type arg = this.BindToType(genericArgNames[i], debugContext); if (arg == null) { return(null); } args.Add(arg); } var argsArray = args.ToArray(); if (!type.AreGenericConstraintsSatisfiedBy(argsArray)) { if (debugContext != null) { string argsStr = ""; foreach (var arg in args) { if (argsStr != "") { argsStr += ", "; } argsStr += arg.GetNiceFullName(); } debugContext.LogWarning("Deserialization type lookup failure: The generic type arguments '" + argsStr + "' do not satisfy the generic constraints of generic type definition '" + type.GetNiceFullName() + "'. All this parsed from the full type name string: '" + typeName + "'"); } return(null); } type = type.MakeGenericType(argsArray); } if (isArray) { type = type.MakeArrayType(arrayRank); } return(type); }
private Type ParseTypeName(string typeName, DebugContext debugContext) { Type type; lock (ASSEMBLY_LOOKUP_LOCK) { // Look for custom defined type name lookups defined with the BindTypeNameToTypeAttribute. if (customTypeNameToTypeBindings.TryGetValue(typeName, out type)) { return(type); } } // Let's try it the traditional .NET way type = Type.GetType(typeName); if (type != null) { return(type); } // Generic/array type name handling type = ParseGenericAndOrArrayType(typeName, debugContext); if (type != null) { return(type); } string typeStr, assemblyStr; ParseName(typeName, out typeStr, out assemblyStr); if (!string.IsNullOrEmpty(typeStr)) { lock (ASSEMBLY_LOOKUP_LOCK) { // Look for custom defined type name lookups defined with the BindTypeNameToTypeAttribute. if (customTypeNameToTypeBindings.TryGetValue(typeStr, out type)) { return(type); } } Assembly assembly; // Try to load from the named assembly if (assemblyStr != null) { lock (ASSEMBLY_LOOKUP_LOCK) { assemblyNameLookUp.TryGetValue(assemblyStr, out assembly); } if (assembly == null) { try { assembly = Assembly.Load(assemblyStr); } catch { } } if (assembly != null) { try { type = assembly.GetType(typeStr); } catch { } // Assembly is invalid if (type != null) { return(type); } } } // Try to check all assemblies for the type string var assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { assembly = assemblies[i]; try { type = assembly.GetType(typeStr, false); } catch { } // Assembly is invalid if (type != null) { return(type); } } } //type = AssemblyUtilities.GetTypeByCachedFullName(typeStr); //if (type != null) return type; return(null); }
/// <summary> /// Binds a name to a type. /// </summary> /// <param name="typeName">The name of the type to bind.</param> /// <param name="debugContext">The debug context to log to.</param> /// <returns>The type that the name has been bound to, or null if the type could not be resolved.</returns> public abstract Type BindToType(string typeName, DebugContext debugContext = null);
/// <summary> /// Bind a type to a name. /// </summary> /// <param name="type">The type to bind.</param> /// <param name="debugContext">The debug context to log to.</param> /// <returns>The name that the type has been bound to.</returns> public abstract string BindToName(Type type, DebugContext debugContext = null);