##// END OF EJS Templates
Fixed promise rejection when there is not specified error handler in the reaction....
Fixed promise rejection when there is not specified error handler in the reaction. FIXED SPELLING IN THE XML CONTAINER CONFIGURATION signleton->singleton Code cleanup Update tests make them working on dotnet core

File last commit:

r289:95896f882995 v3.0.14 v3
r295:28af686e24f7 default
Show More
TypeReference.cs
181 lines | 9.2 KiB | text/x-csharp | CSharpLexer
using System;
using System.Linq;
using System.Text;
namespace Implab.ServiceHost.Unity {
/// <summary>
/// Ссылка на тип, является абстрактной записью имени CLR типа.
/// </summary>
/// <remarks>
/// Ссылка на тип содержит сокращенную информацию о типе и для ее интерпретации
/// требуется некоторый контекст, который позволит превратить ее в полноценный
/// <see cref="Type"/>. Ссылки на тип позволяют записать:
/// <list>
/// <item><description>общие типы, их специализации</description></item>
/// <item><description>вложенные типы</description></item>
/// <item><description>массивы</description></item>
/// </list>
/// <para>
/// Для получения из ссылки на тип конкретного CLR типа используется <see cref="TypeResolver.Resolve(TypeReference, bool)"/>.
/// </para>
/// <para>
/// Ссылку на тип можно создать либо програмно при помощи методов <see cref="Create(string, string, int)"/>,
/// <see cref="Create(string, int)"/>, <see cref="MakeArrayType(int)"/>, <see cref="MakeGenericType(TypeReference[])"/>,
/// либо разобрав строку со спецификацией при помощи метода <see cref="Parse(string)"/>.
/// </para>
/// <para>
/// Спецификация ссыдки на тип имеет следующий вид <c>Name.Space.MyType+Nested{String}[][]</c>, где:
/// <list type="table">
/// <item>
/// <term><c>.</c></term>
/// <description>Разделяет элементы пространства имен</description>
/// <item>
/// <item>
/// <term><c>+</c></term>
/// <description>Разделяет вложенные типы</description>
/// <item>
/// <item>
/// <term><c>[]</c>, <c>[,,,]</c></term>
/// <description>Указывает на то, что тип является массивом, также указывается его размерность</description>
/// <item>
/// <item>
/// <term><c>{}</c>, <c>{,,}</c>, <c>{Int32,String}</c></term>
/// <description>Указывает на то, что тип является общим, также
/// указывается количество параметров, либо конкретные типы для
/// специализации</description>
/// <item>
/// </list>
/// </para>
/// </remarks>
public abstract class TypeReference {
/// <summary>
/// Имя типа без дополнительных элементов, указывающих на то, что он общий или массив.
/// </summary>
/// <remarks>
/// Для массивов это имя его элементов.
/// </remarks>
public abstract string Name { get; }
/// <summary>
/// Пространство имен в котором нахожится тип.
/// </summary>
/// <remarks>
/// Для вложенных типов это пространтство имен типа самого верхнего уровня,
/// для массивов - пространство имен его элементов.
/// </remarks>
public abstract string Namespace { get; }
/// <summary>
/// Количество параметров общего типа.
/// </summary>
/// <remarks>
/// <para>
/// Вложенные типы неявно получают параметры от типов в которых они объявлены,
/// данное свойство это не учитывает, возвращается только количество собственных
/// параметров.
/// </para>
/// <para>
/// Данное свойство используется для получения CRL имени типа.
/// </para>
/// </remarks>
public abstract int GenericParametersCount { get; }
public virtual string ClrName {
get {
return GenericParametersCount != 0 ? $"{Name}`{GenericParametersCount}" : Name;
}
}
/// <summary>
/// Создает ссылку на специализацию текущего типа.
/// </summary>
/// <param name="genericParameters">Ссылки на типы, которые будут использоваться для специализации текущего типа.</param>
/// <returns>Специализация данного типа.</returns>
public virtual SpecializedTypeReference MakeGenericType(TypeReference[] genericParameters) {
if (GenericParametersCount == 0)
throw new InvalidOperationException("Can't specialize a non-geneic type");
if (genericParameters == null || GenericParametersCount != genericParameters.Length)
throw new InvalidOperationException("Generic parameters count mismatch");
return new SpecializedTypeReference(this, genericParameters);
}
/// <summary>
/// Создает ссылку на тип массива указанной размерности, элементами которого являются экземпаляры даннго типа.
/// </summary>
/// <param name="rank">Размерность, если размерность <c>1</c> создается вектор (<see cref="Type.MakeArrayType()"/>).</param>
/// <returns>Ссылка на тип массива</returns>
public ArrayTypeReference MakeArrayType(int rank) {
Safe.ArgumentInRange(rank > 0, nameof(rank));
return new ArrayTypeReference(this, rank);
}
/// <summary>
/// Создает ссылку на вложенный тип.
/// </summary>
/// <param name="name">Имя типа</param>
/// <param name="genericParameters">Количество параметров, если это общий тип, иначе 0.</param>
/// <returns>Ссылка на вложенный тип.</returns>
public TypeReference Create(string name, int genericParameters) {
Safe.ArgumentNotEmpty(name, nameof(name));
Safe.ArgumentInRange(genericParameters >= 0, nameof(genericParameters));
return new NestedTypeReference(this, name, genericParameters);
}
/// <summary>
/// Возвращает строковое представление ссылки на тип.
/// </summary>
/// <returns></returns>
public override string ToString() {
var builder = new StringBuilder();
WriteTypeName(builder);
WriteTypeParams(builder);
return builder.ToString();
}
internal virtual void WriteTypeName(StringBuilder builder) {
if (!string.IsNullOrEmpty(Namespace))
builder
.Append(Namespace)
.Append('.');
builder.Append(Name);
}
internal virtual void WriteTypeParams(StringBuilder builder) {
if (GenericParametersCount > 0)
builder
.Append('{')
.Append(',', GenericParametersCount-1)
.Append('}');
}
internal abstract void Visit(TypeResolutionContext visitor);
/// <summary>
/// Создает ссылку на тип.
/// </summary>
/// <param name="ns">Пространство имен, либо его фрагмент.</param>
/// <param name="name">Имя типа без указания на количество параметров, либо на то, что это массив.</param>
/// <param name="genericParameters">Количество параметров типа, если это общий тип, иначе 0.</param>
/// <returns>Ссылка на тип.</returns>
public static TypeReference Create(string ns, string name, int genericParameters) {
Safe.ArgumentNotEmpty(name, nameof(name));
Safe.ArgumentInRange(genericParameters >= 0, nameof(genericParameters));
return new RootTypeReference(ns, name, genericParameters);
}
/// <summary>
/// Разирает строковую запись ссылки на тип.
/// </summary>
/// <param name="typeSpec">Строковая запись ссылки на тип, например <c>Dictionary{String,String}</c></param>
/// <returns>Ссылка на тип.</returns>
public static TypeReference Parse(string typeSpec) {
var parser = new TypeReferenceParser(typeSpec);
return parser.Parse();
}
}
}