##// END OF EJS Templates
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)...
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete) Implab.ServiceHost: rewritten TypeReference (added support for nested types), stable API

File last commit:

r278:6691aff01de1 v3
r278:6691aff01de1 v3
Show More
TypeResolutionContext.cs
74 lines | 2.7 KiB | text/x-csharp | CSharpLexer
cin
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)...
r278 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;
}
}
}