Mercurial > pub > ImplabNet
comparison 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 |
comparison
equal
deleted
inserted
replaced
277:963b17c275be | 278:6691aff01de1 |
---|---|
1 using System; | |
2 using System.Collections.Generic; | |
3 using Implab.Diagnostics; | |
4 | |
5 namespace Implab.ServiceHost.Unity { | |
6 using static Trace<TypeResolver>; | |
7 | |
8 /// <summary> | |
9 /// Позволяет обойти вложенные типы и собрать цеочку из типов и параметров генериков, которые они предлагают | |
10 /// </summary> | |
11 internal class TypeResolutionContext { | |
12 readonly TypeResolver m_resolver; | |
13 | |
14 | |
15 readonly List<Type> m_genericParameters = new List<Type>(); | |
16 | |
17 public IEnumerable<Type> GenericParameters { get { return m_genericParameters; } } | |
18 | |
19 public Type ResolvedType { get; private set; } | |
20 | |
21 | |
22 public int ArrayRank { get; private set; } | |
23 | |
24 | |
25 public bool ThrowOnFail { get; private set; } | |
26 | |
27 public TypeResolutionContext(TypeResolver resolver, bool throwOnFail) { | |
28 m_resolver = resolver; | |
29 ThrowOnFail = throwOnFail; | |
30 } | |
31 | |
32 public Type MakeType() { | |
33 return m_genericParameters.Count > 0 ? | |
34 ResolvedType?.MakeGenericType(m_genericParameters.ToArray()) : | |
35 ResolvedType; | |
36 } | |
37 | |
38 public void Visit(SpecializedTypeReference typeReference) { | |
39 typeReference.GenericType.Visit(this); | |
40 | |
41 if (ResolvedType != null) { | |
42 foreach (var genericParamRef in typeReference.GenericParameters) { | |
43 var context = new TypeResolutionContext(m_resolver, ThrowOnFail); | |
44 genericParamRef.Visit(context); | |
45 m_genericParameters.Add(context.MakeType()); | |
46 } | |
47 } | |
48 } | |
49 | |
50 public void Visit(NestedTypeReference typeReference) { | |
51 typeReference.DeclaringType.Visit(this); | |
52 if (ResolvedType != null) | |
53 ResolvedType = ResolvedType?.GetNestedType(typeReference.ClrName) ?? Failed(typeReference); | |
54 } | |
55 | |
56 public void Visit(RootTypeReference typeReference) { | |
57 ResolvedType = m_resolver.Resolve(typeReference.Namespace, typeReference.ClrName) ?? Failed(typeReference); | |
58 } | |
59 | |
60 public void Visit(ArrayTypeReference typeReference) { | |
61 var context = new TypeResolutionContext(m_resolver, ThrowOnFail); | |
62 typeReference.ItemsType.Visit(context); | |
63 ResolvedType = typeReference.Rank == 1 ? | |
64 context.MakeType()?.MakeArrayType() : | |
65 context.MakeType()?.MakeArrayType(typeReference.Rank); | |
66 } | |
67 | |
68 Type Failed(TypeReference reference) { | |
69 Log($"Falied to resolve {reference}"); | |
70 if (ThrowOnFail) | |
71 throw new Exception($"Failed to resolve {reference}"); | |
72 return null; | |
73 } | |
74 } | |
75 } |