##// END OF EJS Templates
Working on Unity container xml configuration
cin -
r270:ade80d94dfb5 v3
parent child
Show More
@@ -0,0 +1,7
1 namespace Implab.ServiceHost.Unity
2 {
3 public abstract class AbstractInjectionElement
4 {
5
6 }
7 } No newline at end of file
@@ -0,0 +1,12
1 using System.Xml.Serialization;
2
3 namespace Implab.ServiceHost.Unity {
4 public class ConstructorInjectionElement : AbstractInjectionElement {
5
6 [XmlElement("dependency", typeof(DependencyParameterElement))]
7 [XmlElement("value", typeof(ValueParameterElement))]
8 [XmlElement("serialized", typeof(SerializedParameterElement))]
9 [XmlElement("default", typeof(DefaultParameterElement))]
10 public InjectionParameterElement[] Parameters { get; set; }
11 }
12 } No newline at end of file
@@ -0,0 +1,7
1 namespace Implab.ServiceHost.Unity
2 {
3 public class DefaultParameterElement : InjectionParameterElement
4 {
5
6 }
7 } No newline at end of file
@@ -0,0 +1,7
1 namespace Implab.ServiceHost.Unity
2 {
3 public class DependencyParameterElement : InjectionParameterElement
4 {
5
6 }
7 } No newline at end of file
@@ -0,0 +1,9
1 using System.Xml.Serialization;
2
3 namespace Implab.ServiceHost.Unity {
4 public class InjectionParameterElement {
5
6 [XmlAttribute("type")]
7 public string TypeName { get; set; }
8 }
9 } No newline at end of file
@@ -0,0 +1,16
1 using System.Xml.Serialization;
2
3 namespace Implab.ServiceHost.Unity {
4 public class MethodInjectionElement : AbstractInjectionElement {
5
6 [XmlAttribute("name")]
7 public string Name { get; set; }
8
9 [XmlElement("dependency", typeof(DependencyParameterElement))]
10 [XmlElement("value", typeof(ValueParameterElement))]
11 [XmlElement("serialized", typeof(SerializedParameterElement))]
12 [XmlElement("default", typeof(DefaultParameterElement))]
13 public InjectionParameterElement[] Parameters { get; set; }
14
15 }
16 } No newline at end of file
@@ -0,0 +1,12
1 using System.Xml.Serialization;
2
3 namespace Implab.ServiceHost.Unity {
4 public class PropertyInjectionElement : AbstractInjectionElement {
5
6 [XmlElement("dependency", typeof(DependencyParameterElement))]
7 [XmlElement("value", typeof(ValueParameterElement))]
8 [XmlElement("serialized", typeof(SerializedParameterElement))]
9 [XmlElement("default", typeof(DefaultParameterElement))]
10 public InjectionParameterElement Value { get; set; }
11 }
12 } No newline at end of file
@@ -0,0 +1,7
1 namespace Implab.ServiceHost.Unity
2 {
3 public class SerializedParameterElement : InjectionParameterElement
4 {
5
6 }
7 } No newline at end of file
@@ -0,0 +1,124
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Text.RegularExpressions;
6 using Implab.Diagnostics;
7
8 namespace Implab.ServiceHost.Unity
9 {
10 using static Trace<TypeResolver>;
11 public class TypeResolver
12 {
13 readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>();
14
15 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
16 readonly LinkedList<string> m_namespases = new LinkedList<string>();
17
18 LinkedListNode<string> m_insertAt;
19
20 readonly TypeResolver m_parent;
21
22 public TypeResolver() : this(null) {
23
24 }
25
26 public TypeResolver(TypeResolver parent) {
27 m_insertAt = new LinkedListNode<string>(string.Empty);
28 m_namespases.AddFirst(m_insertAt);
29 }
30
31 public void AddNamespace(string ns) {
32 Safe.ArgumentMatch(ns, nameof(ns), _nsRx);
33 if (m_insertAt != null)
34 m_namespases.AddAfter(m_insertAt, ns);
35 else
36 m_namespases.AddFirst(ns);
37 }
38
39 public void AddMapping(string typeName, Type type) {
40 Safe.ArgumentNotEmpty(typeName, nameof(typeName));
41 Safe.ArgumentNotNull(type, nameof(type));
42
43 m_cache[typeName] = type;
44 }
45
46 public Type Resolve(TypeReference reference) {
47 var args = reference.IsGeneric && !reference.IsOpenGeneric ? reference.GenericParameters?.Select(Resolve).ToArray() : null;
48 var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0;
49
50 Type resolved;
51 if(!m_cache.TryGetValue(reference.ToString(), out resolved)) {
52 resolved = ResolveInternal(reference, args, argc);
53 if (resolved == null)
54 throw new Exception($"Failed to resolve {reference}");
55 m_cache[reference.ToString()] = resolved;
56 }
57
58 return resolved;
59 }
60
61 Type ResolveInternal(TypeReference reference, Type[] args, int argc) {
62 var resolved = ProbeInNamespaces(
63 String.Join(".", new [] { reference.Namespace, reference.TypeName }.Where(x => !string.IsNullOrEmpty(x)) ),
64 args,
65 argc,
66 reference.IsArray,
67 reference.ToString()
68 );
69
70 if (resolved == null && m_parent != null)
71 resolved = m_parent.Resolve(reference);
72
73 return resolved;
74 }
75
76 public Type ProbeInNamespaces(string localName, Type[] args, int argc, bool isArray, string referenceName) {
77 foreach (var ns in m_namespases) {
78 var typeName = FormatName(new [] { ns, localName}, argc, args, isArray);
79
80 var resolved = Probe(typeName);
81 if (resolved != null) {
82 Log("Probe succeed {0} in '{1}': {2} -> {3}", referenceName, ns, typeName, resolved.AssemblyQualifiedName);
83 return resolved;
84 } else {
85 Log("Probe failed {0} in '{1}': {2}", referenceName, ns, typeName);
86 }
87 }
88
89 return null;
90 }
91
92 Type Probe(string typeName) {
93 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
94
95 foreach(var assembly in assemblies) {
96 var type = assembly.GetType(typeName);
97 if (type != null)
98 return type;
99 }
100 return null;
101 }
102
103 string FormatName(string[] parts, int argc, Type[] args, bool isArray) {
104 var builder = new StringBuilder();
105
106 builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x))));
107 if (argc > 0) {
108 builder.Append('`');
109 builder.Append(argc);
110 }
111
112 if (args!= null && args.Length > 0) {
113 builder.Append('[');
114 builder.Append(string.Join(",", args.Select(x => $"[{x.AssemblyQualifiedName}]")));
115 builder.Append(']');
116 }
117
118 if(isArray)
119 builder.Append("[]");
120
121 return builder.ToString();
122 }
123 }
124 } No newline at end of file
@@ -0,0 +1,7
1 namespace Implab.ServiceHost.Unity
2 {
3 public class ValueParameterElement : InjectionParameterElement
4 {
5
6 }
7 } No newline at end of file
@@ -1,48 +1,54
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
12
13 public class Bar {
13 public class Bar {
14
14
15 }
15 }
16
16
17 public string Name { get; set; }
18
17 public int IntValue { get; set; }
19 public int IntValue { get; set; }
18
20
19 public string StringValue { get; set; }
21 public string StringValue { get; set; }
20
22
21 }
23 }
22
24
23 public class Container<T> {
25 public class Container<T> {
24 public Container() {
26 public Container() {
25
27
26 }
28 }
27
29
28 public Container(T instance) {
30 public Container(T instance) {
29 Instance = instance;
31 Instance = instance;
30 }
32 }
31
33
32 public T Instance { get; set; }
34 public T Instance { get; set; }
35
36 public void SetInstance(T value) {
37 Instance = value;
38 }
33 }
39 }
34
40
35 public class Program {
41 public class Program {
36
42
37 static void Main(string[] args) {
43 static void Main(string[] args) {
38 var container = new UnityContainer();
44 var container = new UnityContainer();
39
45
40 var conf = SerializationHelpers.DeserializeFromFile<ContainerElement>("data/sample.xml");
46 var conf = SerializationHelpers.DeserializeFromFile<ContainerElement>("data/sample.xml");
41
47
42 Console.WriteLine($"Registrations: {conf.Registrations.Count}");
48 Console.WriteLine($"Registrations: {conf.Items.Count}");
43
49
44 }
50 }
45
51
46
52
47 }
53 }
48 }
54 }
@@ -1,10 +1,38
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 <namespace name="Implab.Playground"/>
4
3 <!-- foo1 -->
5 <!-- foo1 -->
4 <register name="foo1" type="Foo">
6 <register name="foo1" type="Foo">
7 <property name="Name">
8 <value>FOO!</value>
9 </property>
5 </register>
10 </register>
6
11
7 <!-- foo2 -->
12 <!-- foo2 -->
8 <register name="foo2" type="Foo">
13 <register name="foo2" type="Foo">
14 <property name="Name">
15 <value>GOOD</value>
16 </property>
17 <property name="IntValue">
18 <value>2</value>
19 </property>
9 </register>
20 </register>
21
22 <register type="Foo">
23 </register>
24
25 <register type="Container{}">
26 <constructor/>
27 <method name="SetInstance">
28 <dependency type="T"/>
29 </method>
30 </register>
31
32 <register type="Container{String}">
33 <property name="Instance">
34 <value>Hello!</value>
35 </property>
36 </register>
37
10 </container> No newline at end of file
38 </container>
@@ -1,22 +1,22
1 using System;
1 using System;
2 using System.Xml.Serialization;
2 using System.Xml.Serialization;
3 using Unity.Lifetime;
3 using Unity.Lifetime;
4 using Unity.Registration;
4 using Unity.Registration;
5
5
6 namespace Implab.ServiceHost.Unity
6 namespace Implab.ServiceHost.Unity
7 {
7 {
8 public abstract class AbstractRegistration : IConfigurationElement {
8 public abstract class AbstractRegistration : IConfigurationElement {
9
9
10 /// <summary>
10 /// <summary>
11 /// An optional name for a registration in the container
11 /// An optional name for a registration in the container
12 /// </summary>
12 /// </summary>
13 [XmlAttribute("name")]
13 [XmlAttribute("name")]
14 public string Name {
14 public string Name {
15 get; set;
15 get; set;
16 }
16 }
17
17
18 public void Visit(ConfigurationContext context) {
18 public void Visit(ConfigurationContext context) {
19 context.Visist(this);
19 context.Visit(this);
20 }
20 }
21 }
21 }
22 } No newline at end of file
22 }
@@ -1,14 +1,14
1 using System.Xml.Serialization;
1 using System.Xml.Serialization;
2
2
3 namespace Implab.ServiceHost.Unity
3 namespace Implab.ServiceHost.Unity
4 {
4 {
5 [XmlRoot("assembly", Namespace = Schema.ContainerConfigurationNamespace)]
5 [XmlRoot("assembly", Namespace = Schema.ContainerConfigurationNamespace)]
6 public class AssemblyElement : IConfigurationElement {
6 public class AssemblyElement : IConfigurationElement {
7 [XmlAttribute("name")]
7 [XmlAttribute("name")]
8 public string AssemblyName { get; set; }
8 public string AssemblyName { get; set; }
9
9
10 public void Visit(ConfigurationContext context) {
10 public void Visit(ConfigurationContext context) {
11 throw new System.NotImplementedException();
11 context.Visit(this);
12 }
12 }
13 }
13 }
14 } No newline at end of file
14 }
@@ -1,101 +1,64
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.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 }
26
27 public void AddNamespace(string ns) {
28 Safe.ArgumentMatch(ns, nameof(ns), _nsRx);
29 if (m_insertAt != null)
30 m_namespases.AddAfter(m_insertAt, ns);
31 else
32 m_namespases.AddFirst(ns);
33 }
34
35 public Type Resolve(TypeReference reference) {
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 }
25 }
55
26
56 Type ProbeType(string typeName) {
57 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
58
27
59 foreach(var assembly in assemblies) {
28 public Type Resolve(string typeReference) {
60 var type = assembly.GetType(typeName);
29 return m_resolver.Resolve(TypeReference.Parse(typeReference));
61 if (type != null)
62 return type;
63 }
64 return null;
65 }
30 }
66
31
67 string FormatName(string[] parts, int argc, Type[] args, bool isArray) {
32 internal void Visit(AbstractRegistration descriptor) {
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 } No newline at end of file
64 }
@@ -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<IConfigurationElement> Registrations {get; set; } = new List<IConfigurationElement>();
11 public List<IConfigurationElement> Items {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 = ConfigurationSchema.Default.Deserialize<IConfigurationElement>(reader);
19 var registration = ConfigurationSchema.Default.Deserialize<IConfigurationElement>(reader);
20 Registrations.Add(registration);
20 Items.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,13 +1,13
1 using System.Xml.Serialization;
1 using System.Xml.Serialization;
2
2
3 namespace Implab.ServiceHost.Unity {
3 namespace Implab.ServiceHost.Unity {
4 [XmlRoot("include", Namespace = Schema.ContainerConfigurationNamespace)]
4 [XmlRoot("include", Namespace = Schema.ContainerConfigurationNamespace)]
5 public class IncludeElement : IConfigurationElement {
5 public class IncludeElement : IConfigurationElement {
6 [XmlAttribute("href")]
6 [XmlAttribute("href")]
7 public string Href { get; set; }
7 public string Href { get; set; }
8
8
9 public void Visit(ConfigurationContext context) {
9 public void Visit(ConfigurationContext context) {
10 context.Include(Href);
10 context.Visit(this);
11 }
11 }
12 }
12 }
13 } No newline at end of file
13 }
@@ -1,15 +1,15
1 using System.Xml.Serialization;
1 using System.Xml.Serialization;
2
2
3 namespace Implab.ServiceHost.Unity
3 namespace Implab.ServiceHost.Unity
4 {
4 {
5 [XmlRoot("namespace", Namespace = Schema.ContainerConfigurationNamespace)]
5 [XmlRoot("namespace", Namespace = Schema.ContainerConfigurationNamespace)]
6 public class NamespaceElement : IConfigurationElement {
6 public class NamespaceElement : IConfigurationElement {
7
7
8 [XmlAttribute("name")]
8 [XmlAttribute("name")]
9 public string Name { get; set; }
9 public string Name { get; set; }
10
10
11 public void Visit(ConfigurationContext context) {
11 public void Visit(ConfigurationContext context) {
12 throw new System.NotImplementedException();
12 context.Visit(this);
13 }
13 }
14 }
14 }
15 } No newline at end of file
15 }
@@ -1,36 +1,36
1 using System;
1 using System;
2 using System.Xml.Serialization;
2 using System.Xml.Serialization;
3 using Unity.Lifetime;
3 using Unity.Lifetime;
4 using Unity.Registration;
4 using Unity.Registration;
5
5
6 namespace Implab.ServiceHost.Unity {
6 namespace Implab.ServiceHost.Unity {
7
7
8 [XmlRoot("register", Namespace = Schema.ContainerConfigurationNamespace)]
8 [XmlRoot("register", Namespace = Schema.ContainerConfigurationNamespace)]
9 public class RegisterElement : AbstractRegistration {
9 public class RegisterElement : AbstractRegistration {
10
10
11 /// <summary>
11 /// <summary>
12 /// An optional type specification for the service registration,
12 /// An optional type specification for the service registration,
13 /// must be assignable from the type specified by <see cref="ImplementedType"/>
13 /// must be assignable from the type specified by <see cref="ImplementedType"/>
14 /// </summary>
14 /// </summary>
15 [XmlAttribute("provides")]
15 [XmlAttribute("provides")]
16 public string ProvidesType { get; set; }
16 public string ProvidesType { get; set; }
17
17
18 /// <summary>
18 /// <summary>
19 /// The type which is registered as a service in the container.
19 /// The type which is registered as a service in the container.
20 /// </summary>
20 /// </summary>
21 [XmlAttribute("type")]
21 [XmlAttribute("type")]
22 public string ImplementedType { get; set; }
22 public string ImplementedType { get; set; }
23
23
24 [XmlElement("signleton", typeof(SimgletonLifetimeElement))]
24 [XmlElement("signleton", typeof(SimgletonLifetimeElement))]
25 [XmlElement("context", typeof(ContextLifetimeElement))]
25 [XmlElement("context", typeof(ContextLifetimeElement))]
26 [XmlElement("container", typeof(ContainerLifetimeElement))]
26 [XmlElement("container", typeof(ContainerLifetimeElement))]
27 [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
27 [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
28 public LifetimeElement Lifetime {get; set;}
28 public LifetimeElement Lifetime {get; set;}
29
29
30 [XmlElement("constructor", typeof(ConstructorInjectorElement))]
30 [XmlElement("constructor", typeof(ConstructorInjectionElement))]
31 [XmlElement("property", typeof(PropertyInjectorElement))]
31 [XmlElement("property", typeof(PropertyInjectionElement))]
32 [XmlElement("method", typeof(MethodInjectorElement))]
32 [XmlElement("method", typeof(MethodInjectionElement))]
33 public AbstractInjectorElement[] Injectors { get; set; }
33 public AbstractInjectionElement[] Injectors { get; set; }
34 }
34 }
35
35
36 } No newline at end of file
36 }
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
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