diff Implab.ServiceHost/Unity/TypeResolutionContext.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
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/TypeResolutionContext.cs	Thu May 03 09:59:44 2018 +0300
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using Implab.Diagnostics;
+
+namespace Implab.ServiceHost.Unity {
+    using static Trace<TypeResolver>;
+
+    /// <summary>
+    /// Позволяет обойти вложенные типы и собрать цеочку из типов и параметров генериков, которые они предлагают
+    /// </summary>
+    internal class TypeResolutionContext {
+        readonly TypeResolver m_resolver;
+
+
+        readonly List<Type> m_genericParameters = new List<Type>();
+
+        public IEnumerable<Type> GenericParameters { get { return m_genericParameters; } }
+
+        public Type ResolvedType { get; private set; }
+
+
+        public int ArrayRank { get; private set; }
+
+
+        public bool ThrowOnFail { get; private set; }
+
+        public TypeResolutionContext(TypeResolver resolver, bool throwOnFail) {
+            m_resolver = resolver;
+            ThrowOnFail = throwOnFail;
+        }
+
+        public Type MakeType() {
+            return m_genericParameters.Count > 0 ?
+                ResolvedType?.MakeGenericType(m_genericParameters.ToArray()) :
+                ResolvedType;
+        }
+
+        public void Visit(SpecializedTypeReference typeReference) {
+            typeReference.GenericType.Visit(this);
+
+            if (ResolvedType != null) {
+                foreach (var genericParamRef in typeReference.GenericParameters) {
+                    var context = new TypeResolutionContext(m_resolver, ThrowOnFail);
+                    genericParamRef.Visit(context);
+                    m_genericParameters.Add(context.MakeType());
+                }
+            }
+        }
+
+        public void Visit(NestedTypeReference typeReference) {
+            typeReference.DeclaringType.Visit(this);
+            if (ResolvedType != null)
+                ResolvedType = ResolvedType?.GetNestedType(typeReference.ClrName) ?? Failed(typeReference);
+        }
+
+        public void Visit(RootTypeReference typeReference) {
+            ResolvedType = m_resolver.Resolve(typeReference.Namespace, typeReference.ClrName) ?? Failed(typeReference);
+        }
+
+        public void Visit(ArrayTypeReference typeReference) {
+            var context = new TypeResolutionContext(m_resolver, ThrowOnFail);
+            typeReference.ItemsType.Visit(context);
+            ResolvedType = typeReference.Rank == 1 ?
+                context.MakeType()?.MakeArrayType() :
+                context.MakeType()?.MakeArrayType(typeReference.Rank);
+        }
+
+        Type Failed(TypeReference reference) {
+            Log($"Falied to resolve {reference}");
+            if (ThrowOnFail)
+                throw new Exception($"Failed to resolve {reference}");
+            return null;
+        }
+    }
+}
\ No newline at end of file