TypeResolver.cs
98 lines
| 3.2 KiB
| text/x-csharp
|
CSharpLexer
cin
|
r289 | 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<TypeResolver>; | |||
public class TypeResolver { | |||
readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>(); | |||
Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled); | |||
readonly LinkedList<string> m_namespases = new LinkedList<string>(); | |||
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<string> m_insertAt; | |||
readonly TypeResolver m_parent; | |||
public TypeResolver() : this(null) { | |||
} | |||
public TypeResolver(TypeResolver parent) { | |||
m_parent = parent; | |||
m_insertAt = new LinkedListNode<string>(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; | |||
} | |||
} | |||
} |