comparison Implab.ServiceHost/Unity/ConfigurationContext.cs @ 270:ade80d94dfb5 v3

Working on Unity container xml configuration
author cin
date Wed, 25 Apr 2018 04:44:40 +0300
parents ff581cff7003
children 9d1cca834b05
comparison
equal deleted inserted replaced
269:ff581cff7003 270:ade80d94dfb5
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.Reflection;
9 using System.Text; 9 using System.Text;
10 using global::Unity; 10 using global::Unity;
11 using Implab.Xml;
11 using static Trace<ConfigurationContext>; 12 using static Trace<ConfigurationContext>;
12 13
13 public class ConfigurationContext { 14 public class ConfigurationContext {
14 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
15 readonly LinkedList<string> m_namespases = new LinkedList<string>();
16 15
17 LinkedListNode<string> m_insertAt; 16 readonly TypeResolver m_resolver;
17
18
18 19
19 readonly UnityContainer m_container; 20 readonly UnityContainer m_container;
20 21
21 public ConfigurationContext(UnityContainer container) { 22 public ConfigurationContext(UnityContainer container) {
22 m_container = container ?? new UnityContainer(); 23 m_container = container ?? new UnityContainer();
23 m_insertAt = new LinkedListNode<string>(string.Empty); 24 m_resolver = new TypeResolver();
24 m_namespases.AddFirst(m_insertAt);
25 } 25 }
26 26
27 public void AddNamespace(string ns) { 27
28 Safe.ArgumentMatch(ns, nameof(ns), _nsRx); 28 public Type Resolve(string typeReference) {
29 if (m_insertAt != null) 29 return m_resolver.Resolve(TypeReference.Parse(typeReference));
30 m_namespases.AddAfter(m_insertAt, ns);
31 else
32 m_namespases.AddFirst(ns);
33 } 30 }
34 31
35 public Type Resolve(TypeReference reference) { 32 internal void Visit(AbstractRegistration descriptor) {
36 Safe.ArgumentNotNull(reference, nameof(reference));
37
38 var args = reference.IsGeneric && !reference.IsOpenGeneric ? reference.GenericParameters?.Select(Resolve).ToArray() : null;
39 var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0;
40
41 foreach (var ns in m_namespases) {
42 var typeName = FormatName(new [] { ns, reference.Namespace, reference.TypeName}, argc, args, reference.IsArray);
43
44 var resolved = ProbeType(typeName);
45 if (resolved != null) {
46 Log("Probe succeed {0} in '{1}': {2} -> {3}", reference, ns, typeName, resolved.AssemblyQualifiedName);
47 return resolved;
48 } else {
49 Log("Probe failed {0} in '{1}': {2}", reference, ns, typeName);
50 }
51 }
52
53 throw new Exception($"Failed to resolve: {reference}");
54 }
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
67 string FormatName(string[] parts, int argc, Type[] args, bool isArray) {
68 var builder = new StringBuilder();
69
70 builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x))));
71 if (argc > 0) {
72 builder.Append('`');
73 builder.Append(argc);
74 }
75
76 if (args!= null && args.Length > 0) {
77 builder.Append('[');
78 builder.Append(string.Join(",", args.Select(x => $"[{x.AssemblyQualifiedName}]")));
79 builder.Append(']');
80 }
81
82 if(isArray)
83 builder.Append("[]");
84
85 return builder.ToString();
86 }
87
88 public Type Resolve(string typeReference) {
89 return Resolve(TypeReference.Parse(typeReference));
90 }
91
92 public void Visist(AbstractRegistration descriptor) {
93 33
94 } 34 }
95 35
36 internal void Visit(NamespaceElement namespaceElement) {
37 m_resolver.AddNamespace(namespaceElement.Name);
38 }
39
40 internal void Visit(AssemblyElement assemblyElement) {
41 Assembly.Load(assemblyElement.AssemblyName);
42 }
43
44 internal void Visit(IncludeElement includeElement) {
45 Include(includeElement.Href);
46 }
47
96 public void Include(string file) { 48 public void Include(string file) {
49 var includeContext = new ConfigurationContext(m_container);
50 includeContext.LoadConfig(file);
51 }
97 52
53 public void LoadConfig(string file) {
54 var config = SerializationHelpers.DeserializeFromFile<ContainerElement>(file);
55 Visit(config);
56 }
57
58 public void Visit(ContainerElement containerElement) {
59 foreach (var item in containerElement.Items)
60 item.Visit(this);
98 } 61 }
99 62
100 } 63 }
101 } 64 }