using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using Implab.Diagnostics; namespace Implab.ServiceHost.Unity { using System.Diagnostics; using static Trace; public class TypeResolver { readonly Dictionary m_cache = new Dictionary(); Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled); readonly LinkedList m_namespases = new LinkedList(); internal Type Resolve(string ns, string typeName) { var fullName = string.IsNullOrEmpty(ns) ? typeName : $"{ns}.{typeName}"; return ProbeInNamespaces(fullName); } public Type Resolve(TypeReference typeReference, bool throwOnFail) { var context = new TypeResolutionContext(this, throwOnFail); typeReference.Visit(context); return context.MakeType(); } public Type Resolve(string typeSpec, bool throwOnFail) { Safe.ArgumentNotEmpty(typeSpec, nameof(typeSpec)); var typeReference = TypeReference.Parse(typeSpec); return Resolve(typeReference, throwOnFail); } LinkedListNode m_insertAt; readonly TypeResolver m_parent; public TypeResolver() : this(null) { } public TypeResolver(TypeResolver parent) { m_parent = parent; m_insertAt = new LinkedListNode(string.Empty); m_namespases.AddFirst(m_insertAt); } public void AddNamespace(string ns) { Safe.ArgumentMatch(ns, nameof(ns), _nsRx); if (m_insertAt != null) m_namespases.AddAfter(m_insertAt, ns); else m_namespases.AddFirst(ns); } public void AddMapping(string typeName, Type type) { Safe.ArgumentNotEmpty(typeName, nameof(typeName)); Safe.ArgumentNotNull(type, nameof(type)); m_cache[typeName] = type; } Type ProbeInNamespaces(string localName) { Type resolved; if (!m_cache.TryGetValue(localName, out resolved)) { foreach (var ns in m_namespases) { var typeName = string.IsNullOrEmpty(ns) ? localName : $"{ns}.{localName}"; resolved = Probe(typeName); if (resolved != null) { Log($"Probe '{localName}' -> '{resolved.FullName}'"); break; } } if (resolved == null && m_parent != null) resolved = m_parent.ProbeInNamespaces(localName); if(resolved == null) Log($"Probe '{localName}' failed"); m_cache[localName] = resolved; } return resolved; } Type Probe(string typeName) { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) { var type = assembly.GetType(typeName); if (type != null) return type; } return null; } } }