##// END OF EJS Templates
Working on Unity container xml configuration
cin -
r269:ff581cff7003 v3
parent child
Show More
@@ -0,0 +1,7
1 namespace Implab.ServiceHost.Unity
2 {
3 public abstract class AbstractInjectorElement
4 {
5
6 }
7 } No newline at end of file
@@ -0,0 +1,22
1 using System;
2 using System.Xml.Serialization;
3 using Unity.Lifetime;
4 using Unity.Registration;
5
6 namespace Implab.ServiceHost.Unity
7 {
8 public abstract class AbstractRegistration : IConfigurationElement {
9
10 /// <summary>
11 /// An optional name for a registration in the container
12 /// </summary>
13 [XmlAttribute("name")]
14 public string Name {
15 get; set;
16 }
17
18 public void Visit(ConfigurationContext context) {
19 context.Visist(this);
20 }
21 }
22 } No newline at end of file
@@ -0,0 +1,14
1 using System.Xml.Serialization;
2
3 namespace Implab.ServiceHost.Unity
4 {
5 [XmlRoot("assembly", Namespace = Schema.ContainerConfigurationNamespace)]
6 public class AssemblyElement : IConfigurationElement {
7 [XmlAttribute("name")]
8 public string AssemblyName { get; set; }
9
10 public void Visit(ConfigurationContext context) {
11 throw new System.NotImplementedException();
12 }
13 }
14 } No newline at end of file
@@ -0,0 +1,47
1 using System;
2 using System.Collections.Generic;
3 using System.Reflection;
4 using System.Xml;
5 using System.Xml.Serialization;
6 using Implab.Components;
7
8 namespace Implab.ServiceHost.Unity {
9 public class ConfigurationSchema {
10
11 public static ConfigurationSchema Default { get; private set; } = CreateDefault();
12
13 readonly Dictionary<Tuple<string,string>, LazyAndWeak<XmlSerializer>> m_mappings = new Dictionary<Tuple<string, string>, LazyAndWeak<XmlSerializer>>();
14
15 public void DefineMapping(string name, string ns, Type type) {
16 Safe.ArgumentNotEmpty(name, nameof(name));
17 Safe.ArgumentNotNull(type, nameof(type));
18 ns = ns ?? string.Empty;
19 m_mappings[Tuple.Create(name, ns)] = new LazyAndWeak<XmlSerializer>(() => new XmlSerializer(type), true);
20 }
21
22 public void DefineMapping<T>() {
23 var xmlRoot = typeof(T).GetCustomAttribute<XmlRootAttribute>();
24 var ns = xmlRoot?.Namespace;
25 var root = xmlRoot?.ElementName ?? typeof(T).Name;
26 DefineMapping(root, ns, typeof(T));
27 }
28
29 public T Deserialize<T>(XmlReader reader) {
30 reader.MoveToContent();
31 var name = reader.Name;
32 var ns = reader.NamespaceURI;
33
34 return (T)m_mappings[Tuple.Create(name, ns)].Value.Deserialize(reader);
35 }
36
37 static ConfigurationSchema CreateDefault() {
38 var schema = new ConfigurationSchema();
39
40 schema.DefineMapping<RegisterElement>();
41
42 return schema;
43 }
44
45
46 }
47 } No newline at end of file
@@ -0,0 +1,5
1 namespace Implab.ServiceHost.Unity {
2 public class ConstructorInjectorElement : AbstractInjectorElement {
3
4 }
5 } No newline at end of file
@@ -0,0 +1,10
1 using Unity.Lifetime;
2
3 namespace Implab.ServiceHost.Unity
4 {
5 public class ContainerLifetimeElement : LifetimeElement {
6 public override LifetimeManager GetLifetimeManager(ConfigurationContext ctx) {
7 return new ContainerControlledLifetimeManager();
8 }
9 }
10 } No newline at end of file
@@ -0,0 +1,10
1 using Unity.Lifetime;
2
3 namespace Implab.ServiceHost.Unity
4 {
5 public class ContextLifetimeElement : LifetimeElement {
6 public override LifetimeManager GetLifetimeManager(ConfigurationContext ctx) {
7 return new PerResolveLifetimeManager();
8 }
9 }
10 } No newline at end of file
@@ -0,0 +1,10
1 using Unity.Lifetime;
2
3 namespace Implab.ServiceHost.Unity
4 {
5 public class HierarchicalLifetimeElement : LifetimeElement {
6 public override LifetimeManager GetLifetimeManager(ConfigurationContext ctx) {
7 return new HierarchicalLifetimeManager();
8 }
9 }
10 } No newline at end of file
@@ -0,0 +1,5
1 namespace Implab.ServiceHost.Unity {
2 public interface IConfigurationElement {
3 void Visit(ConfigurationContext context);
4 }
5 } No newline at end of file
@@ -0,0 +1,13
1 using System.Xml.Serialization;
2
3 namespace Implab.ServiceHost.Unity {
4 [XmlRoot("include", Namespace = Schema.ContainerConfigurationNamespace)]
5 public class IncludeElement : IConfigurationElement {
6 [XmlAttribute("href")]
7 public string Href { get; set; }
8
9 public void Visit(ConfigurationContext context) {
10 context.Include(Href);
11 }
12 }
13 } No newline at end of file
@@ -0,0 +1,10
1 using Unity.Lifetime;
2
3 namespace Implab.ServiceHost.Unity
4 {
5 public abstract class LifetimeElement
6 {
7 public abstract LifetimeManager GetLifetimeManager(ConfigurationContext ctx);
8
9 }
10 } No newline at end of file
@@ -0,0 +1,13
1 using System.Xml.Serialization;
2
3 namespace Implab.ServiceHost.Unity {
4 public class MethodInjectorElement : AbstractInjectorElement {
5
6 [XmlAttribute("name")]
7 public string Name { get; set; }
8
9 [XmlElement("params")]
10 public MethodInjectorParameter[] Parameters { get; set; }
11
12 }
13 } No newline at end of file
@@ -0,0 +1,7
1 namespace Implab.ServiceHost.Unity
2 {
3 public class MethodInjectorParameter
4 {
5
6 }
7 } No newline at end of file
@@ -0,0 +1,15
1 using System.Xml.Serialization;
2
3 namespace Implab.ServiceHost.Unity
4 {
5 [XmlRoot("namespace", Namespace = Schema.ContainerConfigurationNamespace)]
6 public class NamespaceElement : IConfigurationElement {
7
8 [XmlAttribute("name")]
9 public string Name { get; set; }
10
11 public void Visit(ConfigurationContext context) {
12 throw new System.NotImplementedException();
13 }
14 }
15 } No newline at end of file
@@ -0,0 +1,6
1 namespace Implab.ServiceHost.Unity {
2 public class PropertyInjectorElement : AbstractInjectorElement {
3
4
5 }
6 } No newline at end of file
@@ -0,0 +1,36
1 using System;
2 using System.Xml.Serialization;
3 using Unity.Lifetime;
4 using Unity.Registration;
5
6 namespace Implab.ServiceHost.Unity {
7
8 [XmlRoot("register", Namespace = Schema.ContainerConfigurationNamespace)]
9 public class RegisterElement : AbstractRegistration {
10
11 /// <summary>
12 /// An optional type specification for the service registration,
13 /// must be assignable from the type specified by <see cref="ImplementedType"/>
14 /// </summary>
15 [XmlAttribute("provides")]
16 public string ProvidesType { get; set; }
17
18 /// <summary>
19 /// The type which is registered as a service in the container.
20 /// </summary>
21 [XmlAttribute("type")]
22 public string ImplementedType { get; set; }
23
24 [XmlElement("signleton", typeof(SimgletonLifetimeElement))]
25 [XmlElement("context", typeof(ContextLifetimeElement))]
26 [XmlElement("container", typeof(ContainerLifetimeElement))]
27 [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
28 public LifetimeElement Lifetime {get; set;}
29
30 [XmlElement("constructor", typeof(ConstructorInjectorElement))]
31 [XmlElement("property", typeof(PropertyInjectorElement))]
32 [XmlElement("method", typeof(MethodInjectorElement))]
33 public AbstractInjectorElement[] Injectors { get; set; }
34 }
35
36 } No newline at end of file
@@ -0,0 +1,10
1 using Unity.Lifetime;
2
3 namespace Implab.ServiceHost.Unity
4 {
5 public class SimgletonLifetimeElement : LifetimeElement {
6 public override LifetimeManager GetLifetimeManager(ConfigurationContext ctx) {
7 return new SingletonLifetimeManager();
8 }
9 }
10 } No newline at end of file
@@ -1,53 +1,48
1 using System;
1 using System;
2 using System.Diagnostics;
2 using System.Diagnostics;
3 using Implab.Diagnostics;
3 using Implab.Diagnostics;
4 using Implab.ServiceHost.Unity;
4 using Implab.ServiceHost.Unity;
5 using Implab.Xml;
5 using Implab.Xml;
6 using Unity;
6 using Unity;
7 using Unity.Injection;
7 using Unity.Injection;
8
8
9 namespace Implab.Playground {
9 namespace Implab.Playground {
10
10
11 public class Foo {
11 public class Foo {
12
13 public class Bar {
14
15 }
16
12 public int IntValue { get; set; }
17 public int IntValue { get; set; }
13
18
14 public string StringValue { get; set; }
19 public string StringValue { get; set; }
15
20
16 }
21 }
17
22
18 public class Container<T> {
23 public class Container<T> {
19 public Container() {
24 public Container() {
20
25
21 }
26 }
22
27
23 public Container(T instance) {
28 public Container(T instance) {
24 Instance = instance;
29 Instance = instance;
25 }
30 }
26
31
27 public T Instance { get; set; }
32 public T Instance { get; set; }
28 }
33 }
29
34
30 public class Program {
35 public class Program {
31
36
32 static void Main(string[] args) {
37 static void Main(string[] args) {
33 var container = new UnityContainer();
38 var container = new UnityContainer();
34
39
35 var listener = new SimpleTraceListener(Console.Out);
40 var conf = SerializationHelpers.DeserializeFromFile<ContainerElement>("data/sample.xml");
36 Trace<ConfigurationContext>.TraceSource.Switch.Level = SourceLevels.All;
37 Trace<ConfigurationContext>.TraceSource.Listeners.Add(listener);
38
39 var c = new Container<int>();
40
41
41 var cts = new ConfigurationContext();
42 Console.WriteLine($"Registrations: {conf.Registrations.Count}");
42 cts.AddNamespace("System");
43 cts.AddNamespace("System.Collections.Generic");
44 cts.AddNamespace("Implab.Playground");
45
43
46 Console.WriteLine(c.GetType().FullName);
47
48 cts.Resolve("Container{Int32}");
49 }
44 }
50
45
51
46
52 }
47 }
53 }
48 }
@@ -1,10 +1,10
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <container xmlns="http://implab.org/schemas/servicehost/unity.v1.xsd">
2 <container xmlns="http://implab.org/schemas/servicehost/unity.v1.xsd">
3 <!-- foo1 -->
3 <!-- foo1 -->
4 <register name="foo1" provides="IFoo" type="Foo">
4 <register name="foo1" type="Foo">
5 </register>
5 </register>
6
6
7 <!-- foo2 -->
7 <!-- foo2 -->
8 <register name="foo2" provides="IFoo" type="Foo">
8 <register name="foo2" type="Foo">
9 </register>
9 </register>
10 </container> No newline at end of file
10 </container>
@@ -1,81 +1,101
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Text.RegularExpressions;
3 using System.Text.RegularExpressions;
4 using Implab.Diagnostics;
4 using Implab.Diagnostics;
5
5
6 namespace Implab.ServiceHost.Unity {
6 namespace Implab.ServiceHost.Unity {
7 using System.Linq;
7 using System.Linq;
8 using System.Reflection;
8 using System.Text;
9 using System.Text;
10 using global::Unity;
9 using static Trace<ConfigurationContext>;
11 using static Trace<ConfigurationContext>;
10
12
11 public class ConfigurationContext {
13 public class ConfigurationContext {
12 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
14 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
13 readonly LinkedList<string> m_namespases = new LinkedList<string>();
15 readonly LinkedList<string> m_namespases = new LinkedList<string>();
14
16
15 LinkedListNode<string> m_insertAt;
17 LinkedListNode<string> m_insertAt;
16
18
17 public ConfigurationContext() {
19 readonly UnityContainer m_container;
20
21 public ConfigurationContext(UnityContainer container) {
22 m_container = container ?? new UnityContainer();
18 m_insertAt = new LinkedListNode<string>(string.Empty);
23 m_insertAt = new LinkedListNode<string>(string.Empty);
19 m_namespases.AddFirst(m_insertAt);
24 m_namespases.AddFirst(m_insertAt);
20 }
25 }
21
26
22 public void AddNamespace(string ns) {
27 public void AddNamespace(string ns) {
23 Safe.ArgumentMatch(ns, nameof(ns), _nsRx);
28 Safe.ArgumentMatch(ns, nameof(ns), _nsRx);
24 if (m_insertAt != null)
29 if (m_insertAt != null)
25 m_namespases.AddAfter(m_insertAt, ns);
30 m_namespases.AddAfter(m_insertAt, ns);
26 else
31 else
27 m_namespases.AddFirst(ns);
32 m_namespases.AddFirst(ns);
28 }
33 }
29
34
30 public Type Resolve(TypeReference reference) {
35 public Type Resolve(TypeReference reference) {
31 Safe.ArgumentNotNull(reference, nameof(reference));
36 Safe.ArgumentNotNull(reference, nameof(reference));
32
37
33 var args = reference.IsGeneric && !reference.IsOpenGeneric ? reference.GenericParameters?.Select(Resolve).ToArray() : null;
38 var args = reference.IsGeneric && !reference.IsOpenGeneric ? reference.GenericParameters?.Select(Resolve).ToArray() : null;
34 var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0;
39 var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0;
35
40
36 foreach (var ns in m_namespases) {
41 foreach (var ns in m_namespases) {
37 var typeName = FormatName(new [] { ns, reference.Namespace, reference.TypeName}, argc, args, reference.IsArray);
42 var typeName = FormatName(new [] { ns, reference.Namespace, reference.TypeName}, argc, args, reference.IsArray);
38
43
39 var resolved = Type.GetType(typeName, false);
44 var resolved = ProbeType(typeName);
40 if (resolved != null) {
45 if (resolved != null) {
41 Log("Probe succeed {0} in '{1}': {2} -> {3}", reference, ns, typeName, resolved.FullName);
46 Log("Probe succeed {0} in '{1}': {2} -> {3}", reference, ns, typeName, resolved.AssemblyQualifiedName);
42 return resolved;
47 return resolved;
43 } else {
48 } else {
44 Log("Probe failed {0} in '{1}': {2}", reference, ns, typeName);
49 Log("Probe failed {0} in '{1}': {2}", reference, ns, typeName);
45 }
50 }
46 }
51 }
47
52
48 throw new Exception($"Failed to resolve: {reference}");
53 throw new Exception($"Failed to resolve: {reference}");
49 }
54 }
50
55
56 Type ProbeType(string typeName) {
57 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
58
59 foreach(var assembly in assemblies) {
60 var type = assembly.GetType(typeName);
61 if (type != null)
62 return type;
63 }
64 return null;
65 }
66
51 string FormatName(string[] parts, int argc, Type[] args, bool isArray) {
67 string FormatName(string[] parts, int argc, Type[] args, bool isArray) {
52 var builder = new StringBuilder();
68 var builder = new StringBuilder();
53
69
54 builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x))));
70 builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x))));
55 if (argc > 0) {
71 if (argc > 0) {
56 builder.Append('`');
72 builder.Append('`');
57 builder.Append(argc);
73 builder.Append(argc);
58 }
74 }
59
75
60 if (args!= null && args.Length > 0) {
76 if (args!= null && args.Length > 0) {
61 builder.Append('[');
77 builder.Append('[');
62 builder.Append(string.Join(",", args.Select(x => x.FullName)));
78 builder.Append(string.Join(",", args.Select(x => $"[{x.AssemblyQualifiedName}]")));
63 builder.Append(']');
79 builder.Append(']');
64 }
80 }
65
81
66 if(isArray)
82 if(isArray)
67 builder.Append("[]");
83 builder.Append("[]");
68
84
69 return builder.ToString();
85 return builder.ToString();
70 }
86 }
71
87
72 public Type Resolve(string typeReference) {
88 public Type Resolve(string typeReference) {
73 return Resolve(TypeReference.Parse(typeReference));
89 return Resolve(TypeReference.Parse(typeReference));
74 }
90 }
75
91
76 public void Register(ServiceElement descriptor) {
92 public void Visist(AbstractRegistration descriptor) {
93
94 }
95
96 public void Include(string file) {
77
97
78 }
98 }
79
99
80 }
100 }
81 } No newline at end of file
101 }
@@ -1,28 +1,28
1 using Implab.Xml;
1 using Implab.Xml;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Xml;
3 using System.Xml;
4 using System.Xml.Schema;
4 using System.Xml.Schema;
5 using System.Xml.Serialization;
5 using System.Xml.Serialization;
6
6
7 namespace Implab.ServiceHost.Unity {
7 namespace Implab.ServiceHost.Unity {
8 [XmlRoot("container", Namespace = Schema.ContainerConfigurationNamespace)]
8 [XmlRoot("container", Namespace = Schema.ContainerConfigurationNamespace)]
9 public class ContainerElement : IXmlSerializable {
9 public class ContainerElement : IXmlSerializable {
10
10
11 public List<ServiceElement> Registrations {get; set; } = new List<ServiceElement>();
11 public List<IConfigurationElement> Registrations {get; set; } = new List<IConfigurationElement>();
12
12
13 public XmlSchema GetSchema() {
13 public XmlSchema GetSchema() {
14 return null;
14 return null;
15 }
15 }
16
16
17 public void ReadXml(XmlReader reader) {
17 public void ReadXml(XmlReader reader) {
18 while(reader.Read() && reader.NodeType != XmlNodeType.EndElement) {
18 while(reader.Read() && reader.NodeType != XmlNodeType.EndElement) {
19 var registration = SerializationHelpers.Deserialize<ServiceElement>(reader);
19 var registration = ConfigurationSchema.Default.Deserialize<IConfigurationElement>(reader);
20 Registrations.Add(registration);
20 Registrations.Add(registration);
21 }
21 }
22 }
22 }
23
23
24 public void WriteXml(XmlWriter writer) {
24 public void WriteXml(XmlWriter writer) {
25 throw new System.NotImplementedException();
25 throw new System.NotImplementedException();
26 }
26 }
27 }
27 }
28 } No newline at end of file
28 }
@@ -1,162 +1,161
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Text.RegularExpressions;
3 using System.Text.RegularExpressions;
4
4
5 namespace Implab.ServiceHost.Unity {
5 namespace Implab.ServiceHost.Unity {
6 internal class TypeReferenceParser {
6 internal class TypeReferenceParser {
7 enum TokenType {
7 enum TokenType {
8 None,
8 None,
9
9
10 Word,
10 Word,
11
11
12 Dot,
12 Dot,
13
13
14 Comma,
14 Comma,
15
15
16 OpenList,
16 OpenList,
17
17
18 CloseList,
18 CloseList,
19
19
20 Eof
20 Eof
21 }
21 }
22
22
23 readonly Regex _tokens = new Regex(@"(\w+)|\s*([\.{},\+])\s*");
23 readonly Regex _tokens = new Regex(@"([\w\+]+)|\s*([\.{},])\s*");
24
24
25 TokenType m_token;
25 TokenType m_token;
26
26
27 string m_tokenValue;
27 string m_tokenValue;
28
28
29 int m_pos;
29 int m_pos;
30
30
31 int m_tokenPos;
31 int m_tokenPos;
32
32
33 readonly string m_text;
33 readonly string m_text;
34
34
35 TokenType Token { get { return m_token; } }
35 TokenType Token { get { return m_token; } }
36
36
37 string TokenValue { get { return m_tokenValue; } }
37 string TokenValue { get { return m_tokenValue; } }
38
38
39 int TokenPos { get { return m_tokenPos; } }
39 int TokenPos { get { return m_tokenPos; } }
40
40
41 public TypeReferenceParser(string text) {
41 public TypeReferenceParser(string text) {
42 Safe.ArgumentNotEmpty(text, nameof(text));
42 Safe.ArgumentNotEmpty(text, nameof(text));
43 m_text = text;
43 m_text = text;
44 }
44 }
45
45
46 bool ReadToken() {
46 bool ReadToken() {
47 if (m_pos >= m_text.Length) {
47 if (m_pos >= m_text.Length) {
48 m_token = TokenType.Eof;
48 m_token = TokenType.Eof;
49 m_tokenValue = null;
49 m_tokenValue = null;
50 return false;
50 return false;
51 }
51 }
52
52
53 var m = _tokens.Match(m_text, m_pos);
53 var m = _tokens.Match(m_text, m_pos);
54
54
55 if (m.Success) {
55 if (m.Success) {
56 m_tokenPos = m_pos;
56 m_tokenPos = m_pos;
57 m_pos += m.Length;
57 m_pos += m.Length;
58 if (m.Groups[1].Success) {
58 if (m.Groups[1].Success) {
59 m_token = TokenType.Word;
59 m_token = TokenType.Word;
60 m_tokenValue = m.Groups[1].Value;
60 m_tokenValue = m.Groups[1].Value;
61 } else if (m.Groups[2].Success) {
61 } else if (m.Groups[2].Success) {
62 m_tokenValue = null;
62 m_tokenValue = null;
63 switch (m.Groups[2].Value) {
63 switch (m.Groups[2].Value) {
64 case "{":
64 case "{":
65 m_token = TokenType.OpenList;
65 m_token = TokenType.OpenList;
66 break;
66 break;
67 case "}":
67 case "}":
68 m_token = TokenType.CloseList;
68 m_token = TokenType.CloseList;
69 break;
69 break;
70 case ".":
70 case ".":
71 case "+":
72 m_token = TokenType.Dot;
71 m_token = TokenType.Dot;
73 break;
72 break;
74 case ",":
73 case ",":
75 m_token = TokenType.Comma;
74 m_token = TokenType.Comma;
76 break;
75 break;
77 }
76 }
78 }
77 }
79 return true;
78 return true;
80 }
79 }
81 throw new FormatException($"Failed to parse '{m_text}' at pos {m_pos}");
80 throw new FormatException($"Failed to parse '{m_text}' at pos {m_pos}");
82 }
81 }
83
82
84 public TypeReference Parse() {
83 public TypeReference Parse() {
85 var result = ReadTypeReference();
84 var result = ReadTypeReference();
86 if (ReadToken())
85 if (ReadToken())
87 ThrowUnexpectedToken();
86 ThrowUnexpectedToken();
88 return result;
87 return result;
89 }
88 }
90
89
91 string[] ReadTypeName() {
90 string[] ReadTypeName() {
92 var parts = new List<string>();
91 var parts = new List<string>();
93
92
94 string current = null;
93 string current = null;
95 bool stop = false;
94 bool stop = false;
96 while ((!stop) && ReadToken()) {
95 while ((!stop) && ReadToken()) {
97 switch (Token) {
96 switch (Token) {
98 case TokenType.Word:
97 case TokenType.Word:
99 if (current != null)
98 if (current != null)
100 ThrowUnexpectedToken();
99 ThrowUnexpectedToken();
101 current = TokenValue;
100 current = TokenValue;
102 break;
101 break;
103 case TokenType.Dot:
102 case TokenType.Dot:
104 if (current == null)
103 if (current == null)
105 ThrowUnexpectedToken();
104 ThrowUnexpectedToken();
106 parts.Add(current);
105 parts.Add(current);
107 current = null;
106 current = null;
108 break;
107 break;
109 default:
108 default:
110 stop = true;
109 stop = true;
111 break;
110 break;
112 }
111 }
113 }
112 }
114 if (current != null)
113 if (current != null)
115 parts.Add(current);
114 parts.Add(current);
116
115
117 if (parts.Count == 0)
116 if (parts.Count == 0)
118 return null;
117 return null;
119
118
120 return parts.ToArray();
119 return parts.ToArray();
121 }
120 }
122
121
123 TypeReference ReadTypeReference() {
122 TypeReference ReadTypeReference() {
124
123
125 var parts = ReadTypeName();
124 var parts = ReadTypeName();
126 if (parts == null)
125 if (parts == null)
127 return null;
126 return null;
128
127
129 var typeReference = new TypeReference {
128 var typeReference = new TypeReference {
130 Namespace = string.Join(".", parts, 0, parts.Length - 1),
129 Namespace = string.Join(".", parts, 0, parts.Length - 1),
131 TypeName = parts[parts.Length - 1]
130 TypeName = parts[parts.Length - 1]
132 };
131 };
133
132
134 switch (Token) {
133 switch (Token) {
135 case TokenType.OpenList:
134 case TokenType.OpenList:
136 typeReference.GenericParameters = ReadTypeReferenceList();
135 typeReference.GenericParameters = ReadTypeReferenceList();
137 if (Token != TokenType.CloseList)
136 if (Token != TokenType.CloseList)
138 ThrowUnexpectedToken();
137 ThrowUnexpectedToken();
139 ReadToken();
138 ReadToken();
140 break;
139 break;
141 }
140 }
142
141
143 return typeReference;
142 return typeReference;
144 }
143 }
145
144
146 TypeReference[] ReadTypeReferenceList() {
145 TypeReference[] ReadTypeReferenceList() {
147 var list = new List<TypeReference>();
146 var list = new List<TypeReference>();
148
147
149 do {
148 do {
150 var typeReference = ReadTypeReference();
149 var typeReference = ReadTypeReference();
151 list.Add(typeReference);
150 list.Add(typeReference);
152 } while (Token == TokenType.Comma);
151 } while (Token == TokenType.Comma);
153
152
154 return list.ToArray();
153 return list.ToArray();
155 }
154 }
156
155
157 void ThrowUnexpectedToken() {
156 void ThrowUnexpectedToken() {
158 throw new FormatException($"Unexpected '{Token}' at pos {TokenPos}: -->{m_text.Substring(TokenPos, Math.Min(m_text.Length - TokenPos, 10))}");
157 throw new FormatException($"Unexpected '{Token}' at pos {TokenPos}: -->{m_text.Substring(TokenPos, Math.Min(m_text.Length - TokenPos, 10))}");
159 }
158 }
160
159
161 }
160 }
162 } No newline at end of file
161 }
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now