Mercurial > pub > ImplabNet
comparison Implab.ServiceHost/Unity/TypeReference.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 | 0be8a6ae8307 |
children |
comparison
equal
deleted
inserted
replaced
277:963b17c275be | 278:6691aff01de1 |
---|---|
1 using System; | 1 using System; |
2 using System.Linq; | 2 using System.Linq; |
3 using System.Text; | 3 using System.Text; |
4 | 4 |
5 namespace Implab.ServiceHost.Unity { | 5 namespace Implab.ServiceHost.Unity { |
6 public class TypeReference { | 6 /// <summary> |
7 public string TypeName { get; set; } | 7 /// Ссылка на тип, является абстрактной записью имени CLR типа. |
8 /// </summary> | |
9 /// <remarks> | |
10 /// Ссылка на тип содержит сокращенную информацию о типе и для ее интерпретации | |
11 /// требуется некоторый контекст, который позволит превратить ее в полноценный | |
12 /// <see cref="Type"/>. Ссылки на тип позволяют записать: | |
13 /// <list> | |
14 /// <item><description>общие типы, их специализации</description></item> | |
15 /// <item><description>вложенные типы</description></item> | |
16 /// <item><description>массивы</description></item> | |
17 /// </list> | |
18 /// <para> | |
19 /// Для получения из ссылки на тип конкретного CLR типа используется <see cref="TypeResolver.Resolve(TypeReference, bool)"/>. | |
20 /// </para> | |
21 /// <para> | |
22 /// Ссылку на тип можно создать либо програмно при помощи методов <see cref="Create(string, string, int)"/>, | |
23 /// <see cref="Create(string, int)"/>, <see cref="MakeArrayType(int)"/>, <see cref="MakeGenericType(TypeReference[])"/>, | |
24 /// либо разобрав строку со спецификацией при помощи метода <see cref="Parse(string)"/>. | |
25 /// </para> | |
26 /// <para> | |
27 /// Спецификация ссыдки на тип имеет следующий вид <c>Name.Space.MyType+Nested{String}[][]</c>, где: | |
28 /// <list type="table"> | |
29 /// <item> | |
30 /// <term><c>.</c></term> | |
31 /// <description>Разделяет элементы пространства имен</description> | |
32 /// <item> | |
33 /// <item> | |
34 /// <term><c>+</c></term> | |
35 /// <description>Разделяет вложенные типы</description> | |
36 /// <item> | |
37 /// <item> | |
38 /// <term><c>[]</c>, <c>[,,,]</c></term> | |
39 /// <description>Указывает на то, что тип является массивом, также указывается его размерность</description> | |
40 /// <item> | |
41 /// <item> | |
42 /// <term><c>{}</c>, <c>{,,}</c>, <c>{Int32,String}</c></term> | |
43 /// <description>Указывает на то, что тип является общим, также | |
44 /// указывается количество параметров, либо конкретные типы для | |
45 /// специализации</description> | |
46 /// <item> | |
47 /// </list> | |
48 /// </para> | |
49 /// </remarks> | |
50 public abstract class TypeReference { | |
8 | 51 |
9 public string Namespace { get; set; } | 52 /// <summary> |
53 /// Имя типа без дополнительных элементов, указывающих на то, что он общий или массив. | |
54 /// </summary> | |
55 /// <remarks> | |
56 /// Для массивов это имя его элементов. | |
57 /// </remarks> | |
58 public abstract string Name { get; } | |
10 | 59 |
11 public TypeReference[] GenericParameters { get; set; } | 60 /// <summary> |
61 /// Пространство имен в котором нахожится тип. | |
62 /// </summary> | |
63 /// <remarks> | |
64 /// Для вложенных типов это пространтство имен типа самого верхнего уровня, | |
65 /// для массивов - пространство имен его элементов. | |
66 /// </remarks> | |
67 public abstract string Namespace { get; } | |
12 | 68 |
13 public bool IsArray { get; set; } | 69 /// <summary> |
70 /// Количество параметров общего типа. | |
71 /// </summary> | |
72 /// <remarks> | |
73 /// <para> | |
74 /// Вложенные типы неявно получают параметры от типов в которых они объявлены, | |
75 /// данное свойство это не учитывает, возвращается только количество собственных | |
76 /// параметров. | |
77 /// </para> | |
78 /// <para> | |
79 /// Данное свойство используется для получения CRL имени типа. | |
80 /// </para> | |
81 /// </remarks> | |
82 public abstract int GenericParametersCount { get; } | |
14 | 83 |
15 public bool IsOpenGeneric { | 84 public virtual string ClrName { |
16 get { | 85 get { |
17 return GenericParameters!=null && GenericParameters.Contains(null); | 86 return GenericParametersCount != 0 ? $"{Name}`{GenericParametersCount}" : Name; |
18 } | 87 } |
19 } | 88 } |
20 | 89 |
21 public bool IsGeneric { | 90 /// <summary> |
22 get { | 91 /// Создает ссылку на специализацию текущего типа. |
23 return GenericParameters != null && GenericParameters.Length > 0; | 92 /// </summary> |
24 } | 93 /// <param name="genericParameters">Ссылки на типы, которые будут использоваться для специализации текущего типа.</param> |
94 /// <returns>Специализация данного типа.</returns> | |
95 public virtual SpecializedTypeReference MakeGenericType(TypeReference[] genericParameters) { | |
96 if (GenericParametersCount == 0) | |
97 throw new InvalidOperationException("Can't specialize a non-geneic type"); | |
98 | |
99 if (genericParameters == null || GenericParametersCount != genericParameters.Length) | |
100 throw new InvalidOperationException("Generic parameters count mismatch"); | |
101 | |
102 return new SpecializedTypeReference(this, genericParameters); | |
25 } | 103 } |
26 | 104 |
105 /// <summary> | |
106 /// Создает ссылку на тип массива указанной размерности, элементами которого являются экземпаляры даннго типа. | |
107 /// </summary> | |
108 /// <param name="rank">Размерность, если размерность <c>1</c> создается вектор (<see cref="Type.MakeArrayType()"/>).</param> | |
109 /// <returns>Ссылка на тип массива</returns> | |
110 public ArrayTypeReference MakeArrayType(int rank) { | |
111 Safe.ArgumentInRange(rank > 0, nameof(rank)); | |
112 | |
113 return new ArrayTypeReference(this, rank); | |
114 } | |
115 | |
116 /// <summary> | |
117 /// Создает ссылку на вложенный тип. | |
118 /// </summary> | |
119 /// <param name="name">Имя типа</param> | |
120 /// <param name="genericParameters">Количество параметров, если это общий тип, иначе 0.</param> | |
121 /// <returns>Ссылка на вложенный тип.</returns> | |
122 public TypeReference Create(string name, int genericParameters) { | |
123 Safe.ArgumentNotEmpty(name, nameof(name)); | |
124 Safe.ArgumentInRange(genericParameters >= 0, nameof(genericParameters)); | |
125 | |
126 return new NestedTypeReference(this, name, genericParameters); | |
127 } | |
128 | |
129 /// <summary> | |
130 /// Возвращает строковое представление ссылки на тип. | |
131 /// </summary> | |
132 /// <returns></returns> | |
27 public override string ToString() { | 133 public override string ToString() { |
28 var builder = new StringBuilder(); | 134 var builder = new StringBuilder(); |
29 | 135 WriteTypeName(builder); |
30 if (!string.IsNullOrEmpty(Namespace)) { | 136 WriteTypeParams(builder); |
31 builder.Append(Namespace); | |
32 builder.Append('.'); | |
33 } | |
34 | |
35 if (!string.IsNullOrEmpty(TypeName)) { | |
36 builder.Append(TypeName); | |
37 } else { | |
38 builder.Append("__unnamed__"); | |
39 } | |
40 | |
41 if (GenericParameters != null && GenericParameters.Length > 0) { | |
42 builder.Append('{'); | |
43 for(var i = 0; i < GenericParameters.Length; i++) { | |
44 if (i > 0) | |
45 builder.Append(','); | |
46 builder.Append(GenericParameters[i]); | |
47 } | |
48 builder.Append('}'); | |
49 } | |
50 | |
51 return builder.ToString(); | 137 return builder.ToString(); |
52 } | 138 } |
53 public static TypeReference Parse(string text) { | 139 |
54 var parser = new TypeReferenceParser(text); | 140 internal virtual void WriteTypeName(StringBuilder builder) { |
141 if (!string.IsNullOrEmpty(Namespace)) | |
142 builder | |
143 .Append(Namespace) | |
144 .Append('.'); | |
145 builder.Append(Name); | |
146 } | |
147 | |
148 internal virtual void WriteTypeParams(StringBuilder builder) { | |
149 if (GenericParametersCount > 0) | |
150 builder | |
151 .Append('{') | |
152 .Append(',', GenericParametersCount-1) | |
153 .Append('}'); | |
154 } | |
155 | |
156 internal abstract void Visit(TypeResolutionContext visitor); | |
157 | |
158 /// <summary> | |
159 /// Создает ссылку на тип. | |
160 /// </summary> | |
161 /// <param name="ns">Пространство имен, либо его фрагмент.</param> | |
162 /// <param name="name">Имя типа без указания на количество параметров, либо на то, что это массив.</param> | |
163 /// <param name="genericParameters">Количество параметров типа, если это общий тип, иначе 0.</param> | |
164 /// <returns>Ссылка на тип.</returns> | |
165 public static TypeReference Create(string ns, string name, int genericParameters) { | |
166 Safe.ArgumentNotEmpty(name, nameof(name)); | |
167 Safe.ArgumentInRange(genericParameters >= 0, nameof(genericParameters)); | |
168 return new RootTypeReference(ns, name, genericParameters); | |
169 } | |
170 | |
171 /// <summary> | |
172 /// Разирает строковую запись ссылки на тип. | |
173 /// </summary> | |
174 /// <param name="typeSpec">Строковая запись ссылки на тип, например <c>Dictionary{String,String}</c></param> | |
175 /// <returns>Ссылка на тип.</returns> | |
176 public static TypeReference Parse(string typeSpec) { | |
177 var parser = new TypeReferenceParser(typeSpec); | |
55 return parser.Parse(); | 178 return parser.Parse(); |
56 } | 179 } |
180 | |
57 } | 181 } |
58 } | 182 } |