diff Implab.ServiceHost/Unity/TypeResolver.cs @ 278:6691aff01de1 v3

Implab: added XmlDefaultSeializer (SerializersPool is now obsolete) Implab.ServiceHost: rewritten TypeReference (added support for nested types), stable API
author cin
date Thu, 03 May 2018 09:59:44 +0300
parents 963b17c275be
children 8714471e8d78
line wrap: on
line diff
--- a/Implab.ServiceHost/Unity/TypeResolver.cs	Sat Apr 28 18:48:09 2018 +0300
+++ b/Implab.ServiceHost/Unity/TypeResolver.cs	Thu May 03 09:59:44 2018 +0300
@@ -6,6 +6,7 @@
 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>();
@@ -13,12 +14,28 @@
         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) {
+            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) {
@@ -42,63 +59,31 @@
             m_cache[typeName] = type;
         }
 
-        public Type Resolve(TypeReference reference) {
-            var args = reference.IsGeneric && !reference.IsOpenGeneric ? reference.GenericParameters?.Select(Resolve).ToArray() : null;
-            var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0;
+        Type ProbeInNamespaces(string localName) {
 
             Type resolved;
-            if (!m_cache.TryGetValue(reference.ToString(), out resolved)) {
-                resolved = ResolveInternal(reference, args, argc);
-                if (resolved == null)
-                    throw new Exception($"Failed to resolve {reference}");
-                m_cache[reference.ToString()] = 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;
         }
 
-        public Type Resolve(string typeSpec) {
-            return Resolve(TypeReference.Parse(typeSpec));
-        }
-
-        Type ResolveInternal(TypeReference reference, Type[] args, int argc) {
-            var resolved = ProbeInNamespaces(
-                String.Join(".", new[] { reference.Namespace, reference.TypeName }.Where(x => !string.IsNullOrEmpty(x))),
-                args,
-                argc,
-                reference.IsArray,
-                reference.ToString()
-            );
-
-            if (resolved == null && m_parent != null)
-                resolved = m_parent.ResolveInternal(reference, args, argc);
-
-            return resolved;
-        }
-
-        public Type ProbeInNamespaces(string localName, Type[] args, int argc, bool isArray, string referenceName) {
-            foreach (var ns in m_namespases) {
-                var typeName = FormatName(new[] { ns, localName }, argc);
-
-                var resolved = Probe(typeName);
-                if (resolved != null) {
-                    if (args != null && args.Length > 0) {
-                        resolved = resolved.MakeGenericType(args);
-                    }
-
-                    if (isArray)
-                        resolved = resolved.MakeArrayType();
-
-                    Log("Probe succeed {0} in '{1}': {2} -> {3}", referenceName, ns, typeName, resolved.AssemblyQualifiedName);
-                    return resolved;
-                } else {
-                    Log("Probe failed {0} in '{1}': {2}", referenceName, ns, typeName);
-                }
-            }
-
-            return null;
-        }
-
         Type Probe(string typeName) {
             var assemblies = AppDomain.CurrentDomain.GetAssemblies();
 
@@ -109,17 +94,5 @@
             }
             return null;
         }
-
-        string FormatName(string[] parts, int argc) {
-            var builder = new StringBuilder();
-
-            builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x))));
-            if (argc > 0) {
-                builder.Append('`');
-                builder.Append(argc);
-            }
-
-            return builder.ToString();
-        }
     }
 }
\ No newline at end of file