##// END OF EJS Templates
preview version of Unity xml configuration
cin -
r272:9d1cca834b05 v3
parent child
Show More
@@ -0,0 +1,119
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Linq;
5 using System.Xml.Serialization;
6 using Implab.Xml;
7 using Unity.Injection;
8 using Unity.Registration;
9
10 namespace Implab.ServiceHost.Unity {
11 class RegistrationContext {
12 readonly TypeResolver m_resolver;
13
14 List<InjectionMember> m_injections = new List<InjectionMember>();
15
16 Type m_defaultType;
17
18 public Type RegistrationType {
19 get;
20 private set;
21 }
22
23 public Type ImplementationType {
24 get;
25 private set;
26 }
27
28 public RegistrationContext(TypeResolver resolver, string typeSpec, string implSpec) {
29 RegistrationType = resolver.Resolve(string.IsNullOrEmpty(typeSpec) ? implSpec : typeSpec);
30
31
32 ImplementationType = string.IsNullOrEmpty(implSpec) ? RegistrationType : resolver.Resolve(implSpec);
33
34 if (RegistrationType.IsGenericTypeDefinition) {
35 m_resolver = new TypeResolver(resolver);
36
37 foreach (var p in ImplementationType.GetGenericArguments())
38 m_resolver.AddMapping(p.Name, p);
39 } else {
40 m_resolver = resolver;
41 }
42
43
44 }
45
46 public InjectionMember[] Injections {
47 get {
48 return m_injections.ToArray();
49 }
50 }
51
52 public void Visit(ConstructorInjectionElement constructorInjection) {
53 var parameters = constructorInjection.Parameters?.Select(x => x.Resolve(this)).ToArray();
54
55 var injection = parameters != null ? new InjectionConstructor(parameters) : new InjectionConstructor();
56 m_injections.Add(injection);
57 }
58
59 public void Visit(MethodInjectionElement methodInjection) {
60 var parameters = methodInjection.Parameters?.Select(x => x.Resolve(this)).ToArray();
61
62 var injection = parameters != null ? new InjectionMethod(methodInjection.Name, parameters) : new InjectionMethod(methodInjection.Name);
63 m_injections.Add(injection);
64 }
65
66 public void Visit(PropertyInjectionElement propertyInjection) {
67 if (propertyInjection.Value == null)
68 throw new Exception($"A value value must be specified for the property '{propertyInjection.Name}'");
69
70 try {
71 m_defaultType = RegistrationType.GetProperty(propertyInjection.Name)?.PropertyType;
72
73 var parameter = propertyInjection.Value.Resolve(this);
74 var injection = new InjectionProperty(propertyInjection.Name, parameter);
75 m_injections.Add(injection);
76
77 } finally {
78 m_defaultType = null;
79 }
80
81 }
82
83 Type ResolveParameterType(InjectionParameterElement injectionParameter) {
84 if (string.IsNullOrEmpty(injectionParameter.TypeName)) {
85 if (m_defaultType == null)
86 throw new Exception($"A type must be specified for the parameter {injectionParameter}");
87 return m_defaultType;
88 }
89 return m_resolver.Resolve(injectionParameter.TypeName);
90 }
91
92 public object Resolve(DefaultParameterElement defaultParameter) {
93 var type = ResolveParameterType(defaultParameter);
94
95 return Safe.CreateDefaultValue(type);
96 }
97
98 public object Resolve(ValueParameterElement valueParameter) {
99 var type = ResolveParameterType(valueParameter);
100
101 return TypeDescriptor.GetConverter(type).ConvertFromString(valueParameter.Value);
102 }
103
104 public object Resolve(SerializedParameterElement serializedParameter) {
105 var type = ResolveParameterType(serializedParameter);
106 if (serializedParameter.Content == null || serializedParameter.Content.Length == 0)
107 return Safe.CreateDefaultValue(type);
108
109 var serializer = new XmlSerializer(type);
110 using (var reader = serializedParameter.Content[0].CreateNavigator().ReadSubtree())
111 return serializer.Deserialize(reader);
112 }
113
114 public InjectionParameterValue Resolve(DependencyParameterElement dependencyParameter) {
115 var type = ResolveParameterType(dependencyParameter);
116 return new ResolvedParameter(type, dependencyParameter.DependencyName);
117 }
118 }
119 } No newline at end of file
@@ -1,58 +1,86
1 using System;
1 using System;
2 using System.Diagnostics;
2 using System.Diagnostics;
3 using System.Linq;
3 using Implab.Diagnostics;
4 using Implab.Diagnostics;
4 using Implab.ServiceHost.Unity;
5 using Implab.ServiceHost.Unity;
5 using Implab.Xml;
6 using Implab.Xml;
6 using Unity;
7 using Unity;
7 using Unity.Injection;
8 using Unity.Injection;
9 using Unity.Registration;
8
10
9 namespace Implab.Playground {
11 namespace Implab.Playground {
10
12
11 public class Foo {
13 public class Foo {
12
14
13 public class Bar {
15 public class Bar {
14
16
15 }
17 }
16
18
17 public string Name { get; set; }
19 public string Name { get; set; }
18
20
19 public int IntValue { get; set; }
21 public int IntValue { get; set; }
20
22
21 public string StringValue { get; set; }
23 public string StringValue { get; set; }
22
24
23 }
25 }
24
26
25 public class Container<T> {
27 public interface IContainer<T> {
28 T Instance { get; set; }
29 }
30
31 public class Container<T> : IContainer<T> {
26 public Container() {
32 public Container() {
27
33
28 }
34 }
29
35
30 public Container(T instance) {
36 public Container(T instance) {
31 Instance = instance;
37 Instance = instance;
32 }
38 }
33
39
34 public T Instance { get; set; }
40 public T Instance { get; set; }
35
41
36 public void SetInstance(T value) {
42 public void SetInstance(T value) {
37 Instance = value;
43 Instance = value;
38 }
44 }
39 }
45 }
40
46
41 public class Program {
47 public class Program {
42
48
43 static void Main(string[] args) {
49 static void Main(string[] args) {
44 var container = new UnityContainer();
50 var container = new UnityContainer();
45
51
46 var ctx = new ConfigurationContext(container);
52 var ctx = new ConfigurationContext(container);
47
53
48 var conf = SerializationHelpers.DeserializeFromFile<ContainerElement>("data/sample.xml");
54 var conf = SerializationHelpers.DeserializeFromFile<ContainerElement>("data/sample.xml");
49
55
50 ctx.Visit(conf);
56 ctx.Visit(conf);
51
57
52 Console.WriteLine($"Registrations: {conf.Items.Count}");
58 DisplayContainerRegistrations(container);
59
60 var instace1 = container.Resolve<IContainer<string>>();
61 var instace2 = container.Resolve<IContainer<Foo>>();
62
63 }
53
64
65 static void DisplayContainerRegistrations(IUnityContainer theContainer) {
66 string regName, regType, mapTo, lifetime;
67 Console.WriteLine("Container has {0} Registrations:",
68 theContainer.Registrations.Count());
69 foreach (ContainerRegistration item in theContainer.Registrations) {
70 regType = item.RegisteredType.FullName;
71 mapTo = item.MappedToType.FullName;
72 regName = item.Name ?? "[default]";
73 lifetime = item.LifetimeManager.LifetimeType.Name;
74 if (mapTo != regType) {
75 mapTo = " -> " + mapTo;
76 } else {
77 mapTo = string.Empty;
78 }
79 lifetime = lifetime.Substring(0, lifetime.Length - "LifetimeManager".Length);
80 Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo, regName, lifetime);
81 }
54 }
82 }
55
83
56
84
57 }
85 }
58 }
86 }
@@ -1,38 +1,40
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="System"/>
3 <namespace name="Implab.Playground"/>
4 <namespace name="Implab.Playground"/>
4
5
5 <!-- foo1 -->
6 <!-- foo1 -->
6 <register name="foo1" type="Foo">
7 <register name="foo1" type="Foo">
7 <property name="Name">
8 <property name="Name">
8 <value>FOO!</value>
9 <value>FOO!</value>
9 </property>
10 </property>
10 </register>
11 </register>
11
12
12 <!-- foo2 -->
13 <!-- foo2 -->
13 <register name="foo2" type="Foo">
14 <register name="foo2" type="Foo">
14 <property name="Name">
15 <property name="Name">
15 <value>GOOD</value>
16 <value>GOOD</value>
16 </property>
17 </property>
17 <property name="IntValue">
18 <property name="IntValue">
18 <value>2</value>
19 <value>2</value>
19 </property>
20 </property>
20 </register>
21 </register>
21
22
22 <register type="Foo">
23 <register type="Foo">
23 </register>
24 </register>
24
25
25 <register type="Container{}">
26 <register provides="IContainer{}" type="Container{}">
26 <constructor/>
27 <constructor/>
27 <method name="SetInstance">
28 <method name="SetInstance">
28 <dependency type="T"/>
29 <dependency type="T"/>
29 </method>
30 </method>
30 </register>
31 </register>
31
32
32 <register type="Container{String}">
33 <register provides="IContainer{String}" type="Container{String}">
33 <property name="Instance">
34 <constructor/>
34 <value>Hello!</value>
35 <method name="SetInstance">
35 </property>
36 <value type="String">Hello!</value>
37 </method>
36 </register>
38 </register>
37
39
38 </container> No newline at end of file
40 </container>
@@ -1,7 +1,8
1 using System;
2
1 namespace Implab.ServiceHost.Unity
3 namespace Implab.ServiceHost.Unity
2 {
4 {
3 public abstract class AbstractInjectionElement
5 public abstract class AbstractInjectionElement {
4 {
6 internal abstract void Visit(RegistrationContext context);
5
6 }
7 }
7 } No newline at end of file
8 }
@@ -1,34 +1,32
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 [XmlElement("signleton", typeof(SimgletonLifetimeElement))]
18 [XmlElement("signleton", typeof(SimgletonLifetimeElement))]
19 [XmlElement("context", typeof(ContextLifetimeElement))]
19 [XmlElement("context", typeof(ContextLifetimeElement))]
20 [XmlElement("container", typeof(ContainerLifetimeElement))]
20 [XmlElement("container", typeof(ContainerLifetimeElement))]
21 [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
21 [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
22 public LifetimeElement Lifetime {get; set;}
22 public LifetimeElement Lifetime {get; set;}
23
23
24 /// <summary>
24 /// <summary>
25 /// A type specification for the service registration,
25 /// A type specification for the service registration,
26 /// </summary>
26 /// </summary>
27 [XmlAttribute("provides")]
27 [XmlAttribute("provides")]
28 public string ProvidesType { get; set; }
28 public string ProvidesType { get; set; }
29
29
30 public void Visit(ConfigurationContext context) {
30 public abstract void Visit(ConfigurationContext context);
31 context.Visit(this);
32 }
33 }
31 }
34 } No newline at end of file
32 }
@@ -1,64 +1,78
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 global::Unity.Registration;
11 using Implab.Xml;
12 using Implab.Xml;
12 using static Trace<ConfigurationContext>;
13 using static Trace<ConfigurationContext>;
13
14
14 public class ConfigurationContext {
15 public class ConfigurationContext {
15
16
16 readonly TypeResolver m_resolver;
17 readonly TypeResolver m_resolver;
17
18
18
19
20 readonly UnityContainer m_container;
19 readonly UnityContainer m_container;
21
20
22 public ConfigurationContext(UnityContainer container) {
21 public ConfigurationContext(UnityContainer container) {
23 m_container = container ?? new UnityContainer();
22 m_container = container ?? new UnityContainer();
24 m_resolver = new TypeResolver();
23 m_resolver = new TypeResolver();
25 }
24 }
26
25
27
26
28 public Type Resolve(string typeReference) {
27 public Type Resolve(string typeReference) {
29 return m_resolver.Resolve(TypeReference.Parse(typeReference));
28 return m_resolver.Resolve(TypeReference.Parse(typeReference));
30 }
29 }
31
30
32 internal void Visit(AbstractRegistration descriptor) {
31 internal void Visit(RegisterElement descriptor) {
32 var registrationContext = new RegistrationContext(m_resolver, descriptor.ProvidesType, descriptor.ImplementationType);
33
34 if (descriptor.Injectors != null) {
35 foreach (var injector in descriptor.Injectors) {
36 injector.Visit(registrationContext);
37 }
38 }
39
40 m_container.RegisterType(
41 registrationContext.RegistrationType,
42 registrationContext.ImplementationType,
43 descriptor.Name,
44 descriptor.Lifetime?.GetLifetimeManager(this),
45 registrationContext.Injections
46 );
33
47
34 }
48 }
35
49
36 internal void Visit(NamespaceElement namespaceElement) {
50 internal void Visit(NamespaceElement namespaceElement) {
37 m_resolver.AddNamespace(namespaceElement.Name);
51 m_resolver.AddNamespace(namespaceElement.Name);
38 }
52 }
39
53
40 internal void Visit(AssemblyElement assemblyElement) {
54 internal void Visit(AssemblyElement assemblyElement) {
41 Assembly.Load(assemblyElement.AssemblyName);
55 Assembly.Load(assemblyElement.AssemblyName);
42 }
56 }
43
57
44 internal void Visit(IncludeElement includeElement) {
58 internal void Visit(IncludeElement includeElement) {
45 Include(includeElement.Href);
59 Include(includeElement.Href);
46 }
60 }
47
61
48 public void Include(string file) {
62 public void Include(string file) {
49 var includeContext = new ConfigurationContext(m_container);
63 var includeContext = new ConfigurationContext(m_container);
50 includeContext.LoadConfig(file);
64 includeContext.LoadConfig(file);
51 }
65 }
52
66
53 public void LoadConfig(string file) {
67 public void LoadConfig(string file) {
54 var config = SerializationHelpers.DeserializeFromFile<ContainerElement>(file);
68 var config = SerializationHelpers.DeserializeFromFile<ContainerElement>(file);
55 Visit(config);
69 Visit(config);
56 }
70 }
57
71
58 public void Visit(ContainerElement containerElement) {
72 public void Visit(ContainerElement containerElement) {
59 foreach (var item in containerElement.Items)
73 foreach (var item in containerElement.Items)
60 item.Visit(this);
74 item.Visit(this);
61 }
75 }
62
76
63 }
77 }
64 } No newline at end of file
78 }
@@ -1,12 +1,16
1 using System.Xml.Serialization;
1 using System.Xml.Serialization;
2
2
3 namespace Implab.ServiceHost.Unity {
3 namespace Implab.ServiceHost.Unity {
4 public class ConstructorInjectionElement : AbstractInjectionElement {
4 public class ConstructorInjectionElement : AbstractInjectionElement {
5
5
6 [XmlElement("dependency", typeof(DependencyParameterElement))]
6 [XmlElement("dependency", typeof(DependencyParameterElement))]
7 [XmlElement("value", typeof(ValueParameterElement))]
7 [XmlElement("value", typeof(ValueParameterElement))]
8 [XmlElement("serialized", typeof(SerializedParameterElement))]
8 [XmlElement("serialized", typeof(SerializedParameterElement))]
9 [XmlElement("default", typeof(DefaultParameterElement))]
9 [XmlElement("default", typeof(DefaultParameterElement))]
10 public InjectionParameterElement[] Parameters { get; set; }
10 public InjectionParameterElement[] Parameters { get; set; }
11
12 internal override void Visit(RegistrationContext context) {
13 context.Visit(this);
14 }
11 }
15 }
12 } No newline at end of file
16 }
@@ -1,7 +1,8
1 namespace Implab.ServiceHost.Unity
1 namespace Implab.ServiceHost.Unity
2 {
2 {
3 public class DefaultParameterElement : InjectionParameterElement
3 public class DefaultParameterElement : InjectionParameterElement {
4 {
4 internal override object Resolve(RegistrationContext context) {
5
5 return context.Resolve(this);
6 }
6 }
7 }
7 } No newline at end of file
8 }
@@ -1,7 +1,16
1 namespace Implab.ServiceHost.Unity
1 using System.Xml.Serialization;
2 {
2
3 public class DependencyParameterElement : InjectionParameterElement
3 namespace Implab.ServiceHost.Unity {
4 {
4 public class DependencyParameterElement : InjectionParameterElement {
5
5
6 [XmlAttribute("name")]
7 public string DependencyName { get; set; }
8
9 [XmlAttribute("optional")]
10 public bool Optional { get; set; }
11
12 internal override object Resolve(RegistrationContext context) {
13 return context.Resolve(this);
14 }
6 }
15 }
7 } No newline at end of file
16 }
@@ -1,9 +1,11
1 using System.Xml.Serialization;
1 using System.Xml.Serialization;
2
2
3 namespace Implab.ServiceHost.Unity {
3 namespace Implab.ServiceHost.Unity {
4 public class InjectionParameterElement {
4 public abstract class InjectionParameterElement {
5
5
6 [XmlAttribute("type")]
6 [XmlAttribute("type")]
7 public string TypeName { get; set; }
7 public string TypeName { get; set; }
8
9 internal abstract object Resolve(RegistrationContext context);
8 }
10 }
9 } No newline at end of file
11 }
@@ -1,16 +1,19
1 using System.Xml.Serialization;
1 using System.Xml.Serialization;
2
2
3 namespace Implab.ServiceHost.Unity {
3 namespace Implab.ServiceHost.Unity {
4 public class MethodInjectionElement : AbstractInjectionElement {
4 public class MethodInjectionElement : AbstractInjectionElement {
5
5
6 [XmlAttribute("name")]
6 [XmlAttribute("name")]
7 public string Name { get; set; }
7 public string Name { get; set; }
8
8
9 [XmlElement("dependency", typeof(DependencyParameterElement))]
9 [XmlElement("dependency", typeof(DependencyParameterElement))]
10 [XmlElement("value", typeof(ValueParameterElement))]
10 [XmlElement("value", typeof(ValueParameterElement))]
11 [XmlElement("serialized", typeof(SerializedParameterElement))]
11 [XmlElement("serialized", typeof(SerializedParameterElement))]
12 [XmlElement("default", typeof(DefaultParameterElement))]
12 [XmlElement("default", typeof(DefaultParameterElement))]
13 public InjectionParameterElement[] Parameters { get; set; }
13 public InjectionParameterElement[] Parameters { get; set; }
14
14
15 internal override void Visit(RegistrationContext context) {
16 context.Visit(this);
17 }
15 }
18 }
16 } No newline at end of file
19 }
@@ -1,12 +1,19
1 using System.Xml.Serialization;
1 using System.Xml.Serialization;
2
2
3 namespace Implab.ServiceHost.Unity {
3 namespace Implab.ServiceHost.Unity {
4 public class PropertyInjectionElement : AbstractInjectionElement {
4 public class PropertyInjectionElement : AbstractInjectionElement {
5
5
6 [XmlAttribute("name")]
7 public string Name { get; set; }
8
6 [XmlElement("dependency", typeof(DependencyParameterElement))]
9 [XmlElement("dependency", typeof(DependencyParameterElement))]
7 [XmlElement("value", typeof(ValueParameterElement))]
10 [XmlElement("value", typeof(ValueParameterElement))]
8 [XmlElement("serialized", typeof(SerializedParameterElement))]
11 [XmlElement("serialized", typeof(SerializedParameterElement))]
9 [XmlElement("default", typeof(DefaultParameterElement))]
12 [XmlElement("default", typeof(DefaultParameterElement))]
10 public InjectionParameterElement Value { get; set; }
13 public InjectionParameterElement Value { get; set; }
14
15 internal override void Visit(RegistrationContext context) {
16 context.Visit(this);
17 }
11 }
18 }
12 } No newline at end of file
19 }
@@ -1,24 +1,28
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 which is registered as a service in the container, must be assignable to <see cref="ProvidesType">.
12 /// An optional type which is registered as a service in the container, must be assignable to <see cref="ProvidesType">.
13 /// </summary>
13 /// </summary>
14 [XmlAttribute("type")]
14 [XmlAttribute("type")]
15 public string ImplementedType { get; set; }
15 public string ImplementationType { get; set; }
16
16
17
17
18 [XmlElement("constructor", typeof(ConstructorInjectionElement))]
18 [XmlElement("constructor", typeof(ConstructorInjectionElement))]
19 [XmlElement("property", typeof(PropertyInjectionElement))]
19 [XmlElement("property", typeof(PropertyInjectionElement))]
20 [XmlElement("method", typeof(MethodInjectionElement))]
20 [XmlElement("method", typeof(MethodInjectionElement))]
21 public AbstractInjectionElement[] Injectors { get; set; }
21 public AbstractInjectionElement[] Injectors { get; set; }
22
23 public override void Visit(ConfigurationContext context) {
24 context.Visit(this);
25 }
22 }
26 }
23
27
24 } No newline at end of file
28 }
@@ -1,12 +1,16
1 using System.Xml;
1 using System.Xml;
2 using System.Xml.Schema;
2 using System.Xml.Schema;
3 using System.Xml.Serialization;
3 using System.Xml.Serialization;
4
4
5 namespace Implab.ServiceHost.Unity
5 namespace Implab.ServiceHost.Unity
6 {
6 {
7 public class SerializedParameterElement : InjectionParameterElement {
7 public class SerializedParameterElement : InjectionParameterElement {
8
8
9 [XmlAnyElement]
9 [XmlAnyElement]
10 public XmlElement[] Content { get; set; }
10 public XmlElement[] Content { get; set; }
11
12 internal override object Resolve(RegistrationContext context) {
13 return context.Resolve(this);
14 }
11 }
15 }
12 } No newline at end of file
16 }
@@ -1,124 +1,129
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5 using System.Text.RegularExpressions;
5 using System.Text.RegularExpressions;
6 using Implab.Diagnostics;
6 using Implab.Diagnostics;
7
7
8 namespace Implab.ServiceHost.Unity
8 namespace Implab.ServiceHost.Unity
9 {
9 {
10 using static Trace<TypeResolver>;
10 using static Trace<TypeResolver>;
11 public class TypeResolver
11 public class TypeResolver
12 {
12 {
13 readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>();
13 readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>();
14
14
15 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
15 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
16 readonly LinkedList<string> m_namespases = new LinkedList<string>();
16 readonly LinkedList<string> m_namespases = new LinkedList<string>();
17
17
18 LinkedListNode<string> m_insertAt;
18 LinkedListNode<string> m_insertAt;
19
19
20 readonly TypeResolver m_parent;
20 readonly TypeResolver m_parent;
21
21
22 public TypeResolver() : this(null) {
22 public TypeResolver() : this(null) {
23
23
24 }
24 }
25
25
26 public TypeResolver(TypeResolver parent) {
26 public TypeResolver(TypeResolver parent) {
27 m_parent = parent;
27 m_insertAt = new LinkedListNode<string>(string.Empty);
28 m_insertAt = new LinkedListNode<string>(string.Empty);
28 m_namespases.AddFirst(m_insertAt);
29 m_namespases.AddFirst(m_insertAt);
29 }
30 }
30
31
31 public void AddNamespace(string ns) {
32 public void AddNamespace(string ns) {
32 Safe.ArgumentMatch(ns, nameof(ns), _nsRx);
33 Safe.ArgumentMatch(ns, nameof(ns), _nsRx);
33 if (m_insertAt != null)
34 if (m_insertAt != null)
34 m_namespases.AddAfter(m_insertAt, ns);
35 m_namespases.AddAfter(m_insertAt, ns);
35 else
36 else
36 m_namespases.AddFirst(ns);
37 m_namespases.AddFirst(ns);
37 }
38 }
38
39
39 public void AddMapping(string typeName, Type type) {
40 public void AddMapping(string typeName, Type type) {
40 Safe.ArgumentNotEmpty(typeName, nameof(typeName));
41 Safe.ArgumentNotEmpty(typeName, nameof(typeName));
41 Safe.ArgumentNotNull(type, nameof(type));
42 Safe.ArgumentNotNull(type, nameof(type));
42
43
43 m_cache[typeName] = type;
44 m_cache[typeName] = type;
44 }
45 }
45
46
46 public Type Resolve(TypeReference reference) {
47 public Type Resolve(TypeReference reference) {
47 var args = reference.IsGeneric && !reference.IsOpenGeneric ? reference.GenericParameters?.Select(Resolve).ToArray() : null;
48 var args = reference.IsGeneric && !reference.IsOpenGeneric ? reference.GenericParameters?.Select(Resolve).ToArray() : null;
48 var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0;
49 var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0;
49
50
50 Type resolved;
51 Type resolved;
51 if(!m_cache.TryGetValue(reference.ToString(), out resolved)) {
52 if(!m_cache.TryGetValue(reference.ToString(), out resolved)) {
52 resolved = ResolveInternal(reference, args, argc);
53 resolved = ResolveInternal(reference, args, argc);
53 if (resolved == null)
54 if (resolved == null)
54 throw new Exception($"Failed to resolve {reference}");
55 throw new Exception($"Failed to resolve {reference}");
55 m_cache[reference.ToString()] = resolved;
56 m_cache[reference.ToString()] = resolved;
56 }
57 }
57
58
58 return resolved;
59 return resolved;
59 }
60 }
60
61
62 public Type Resolve(string typeSpec) {
63 return Resolve(TypeReference.Parse(typeSpec));
64 }
65
61 Type ResolveInternal(TypeReference reference, Type[] args, int argc) {
66 Type ResolveInternal(TypeReference reference, Type[] args, int argc) {
62 var resolved = ProbeInNamespaces(
67 var resolved = ProbeInNamespaces(
63 String.Join(".", new [] { reference.Namespace, reference.TypeName }.Where(x => !string.IsNullOrEmpty(x)) ),
68 String.Join(".", new [] { reference.Namespace, reference.TypeName }.Where(x => !string.IsNullOrEmpty(x)) ),
64 args,
69 args,
65 argc,
70 argc,
66 reference.IsArray,
71 reference.IsArray,
67 reference.ToString()
72 reference.ToString()
68 );
73 );
69
74
70 if (resolved == null && m_parent != null)
75 if (resolved == null && m_parent != null)
71 resolved = m_parent.Resolve(reference);
76 resolved = m_parent.Resolve(reference);
72
77
73 return resolved;
78 return resolved;
74 }
79 }
75
80
76 public Type ProbeInNamespaces(string localName, Type[] args, int argc, bool isArray, string referenceName) {
81 public Type ProbeInNamespaces(string localName, Type[] args, int argc, bool isArray, string referenceName) {
77 foreach (var ns in m_namespases) {
82 foreach (var ns in m_namespases) {
78 var typeName = FormatName(new [] { ns, localName}, argc, args, isArray);
83 var typeName = FormatName(new [] { ns, localName}, argc, args, isArray);
79
84
80 var resolved = Probe(typeName);
85 var resolved = Probe(typeName);
81 if (resolved != null) {
86 if (resolved != null) {
82 Log("Probe succeed {0} in '{1}': {2} -> {3}", referenceName, ns, typeName, resolved.AssemblyQualifiedName);
87 Log("Probe succeed {0} in '{1}': {2} -> {3}", referenceName, ns, typeName, resolved.AssemblyQualifiedName);
83 return resolved;
88 return resolved;
84 } else {
89 } else {
85 Log("Probe failed {0} in '{1}': {2}", referenceName, ns, typeName);
90 Log("Probe failed {0} in '{1}': {2}", referenceName, ns, typeName);
86 }
91 }
87 }
92 }
88
93
89 return null;
94 return null;
90 }
95 }
91
96
92 Type Probe(string typeName) {
97 Type Probe(string typeName) {
93 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
98 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
94
99
95 foreach(var assembly in assemblies) {
100 foreach(var assembly in assemblies) {
96 var type = assembly.GetType(typeName);
101 var type = assembly.GetType(typeName);
97 if (type != null)
102 if (type != null)
98 return type;
103 return type;
99 }
104 }
100 return null;
105 return null;
101 }
106 }
102
107
103 string FormatName(string[] parts, int argc, Type[] args, bool isArray) {
108 string FormatName(string[] parts, int argc, Type[] args, bool isArray) {
104 var builder = new StringBuilder();
109 var builder = new StringBuilder();
105
110
106 builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x))));
111 builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x))));
107 if (argc > 0) {
112 if (argc > 0) {
108 builder.Append('`');
113 builder.Append('`');
109 builder.Append(argc);
114 builder.Append(argc);
110 }
115 }
111
116
112 if (args!= null && args.Length > 0) {
117 if (args!= null && args.Length > 0) {
113 builder.Append('[');
118 builder.Append('[');
114 builder.Append(string.Join(",", args.Select(x => $"[{x.AssemblyQualifiedName}]")));
119 builder.Append(string.Join(",", args.Select(x => $"[{x.AssemblyQualifiedName}]")));
115 builder.Append(']');
120 builder.Append(']');
116 }
121 }
117
122
118 if(isArray)
123 if(isArray)
119 builder.Append("[]");
124 builder.Append("[]");
120
125
121 return builder.ToString();
126 return builder.ToString();
122 }
127 }
123 }
128 }
124 } No newline at end of file
129 }
@@ -1,7 +1,14
1 using System.Xml.Serialization;
2
1 namespace Implab.ServiceHost.Unity
3 namespace Implab.ServiceHost.Unity
2 {
4 {
3 public class ValueParameterElement : InjectionParameterElement
5 public class ValueParameterElement : InjectionParameterElement
4 {
6 {
7 [XmlText]
8 public string Value { get; set; }
5
9
10 internal override object Resolve(RegistrationContext context) {
11 return context.Resolve(this);
12 }
6 }
13 }
7 } No newline at end of file
14 }
@@ -1,182 +1,189
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5 using System.Text.RegularExpressions;
5 using System.Text.RegularExpressions;
6 using System.Diagnostics;
6 using System.Diagnostics;
7 using System.Collections;
7 using System.Collections;
8 using System.Runtime.CompilerServices;
8 using System.Runtime.CompilerServices;
9 using System.Threading.Tasks;
9 using System.Threading.Tasks;
10 using System.Threading;
10 using System.Threading;
11
11
12 #if NET_4_5
12 #if NET_4_5
13 using System.Threading.Tasks;
13 using System.Threading.Tasks;
14 #endif
14 #endif
15
15
16 namespace Implab
16 namespace Implab
17 {
17 {
18 public static class Safe
18 public static class Safe
19 {
19 {
20 [MethodImpl(MethodImplOptions.AggressiveInlining)]
20 [MethodImpl(MethodImplOptions.AggressiveInlining)]
21 public static void ArgumentAssert(bool condition, string paramName) {
21 public static void ArgumentAssert(bool condition, string paramName) {
22 if (!condition)
22 if (!condition)
23 throw new ArgumentException("The parameter is invalid", paramName);
23 throw new ArgumentException("The parameter is invalid", paramName);
24 }
24 }
25
25
26 [MethodImpl(MethodImplOptions.AggressiveInlining)]
26 [MethodImpl(MethodImplOptions.AggressiveInlining)]
27 public static void ArgumentMatch(string value, string paramName, Regex rx) {
27 public static void ArgumentMatch(string value, string paramName, Regex rx) {
28 if (rx == null)
28 if (rx == null)
29 throw new ArgumentNullException("rx");
29 throw new ArgumentNullException("rx");
30 if (!rx.IsMatch(value))
30 if (!rx.IsMatch(value))
31 throw new ArgumentException(String.Format("The prameter value must match {0}", rx), paramName);
31 throw new ArgumentException(String.Format("The prameter value must match {0}", rx), paramName);
32 }
32 }
33
33
34 [MethodImpl(MethodImplOptions.AggressiveInlining)]
34 [MethodImpl(MethodImplOptions.AggressiveInlining)]
35 public static void ArgumentNotEmpty(string value, string paramName) {
35 public static void ArgumentNotEmpty(string value, string paramName) {
36 if (String.IsNullOrEmpty(value))
36 if (String.IsNullOrEmpty(value))
37 throw new ArgumentException("The parameter can't be empty", paramName);
37 throw new ArgumentException("The parameter can't be empty", paramName);
38 }
38 }
39
39
40 [MethodImpl(MethodImplOptions.AggressiveInlining)]
40 [MethodImpl(MethodImplOptions.AggressiveInlining)]
41 public static void ArgumentNotEmpty<T>(T[] value, string paramName) {
41 public static void ArgumentNotEmpty<T>(T[] value, string paramName) {
42 if (value == null || value.Length == 0)
42 if (value == null || value.Length == 0)
43 throw new ArgumentException("The array must be not emty", paramName);
43 throw new ArgumentException("The array must be not emty", paramName);
44 }
44 }
45
45
46 [MethodImpl(MethodImplOptions.AggressiveInlining)]
46 [MethodImpl(MethodImplOptions.AggressiveInlining)]
47 public static void ArgumentNotNull(object value, string paramName) {
47 public static void ArgumentNotNull(object value, string paramName) {
48 if (value == null)
48 if (value == null)
49 throw new ArgumentNullException(paramName);
49 throw new ArgumentNullException(paramName);
50 }
50 }
51
51
52 [MethodImpl(MethodImplOptions.AggressiveInlining)]
52 [MethodImpl(MethodImplOptions.AggressiveInlining)]
53 internal static void ArgumentGreaterEqThan(int value, int min, string paramName) {
53 internal static void ArgumentGreaterEqThan(int value, int min, string paramName) {
54 if (value < min)
54 if (value < min)
55 throw new ArgumentOutOfRangeException(paramName);
55 throw new ArgumentOutOfRangeException(paramName);
56 }
56 }
57
57
58 public static object CreateDefaultValue(Type type) {
59 if (type.IsValueType)
60 return Activator.CreateInstance(type);
61
62 return null;
63 }
64
58 [MethodImpl(MethodImplOptions.AggressiveInlining)]
65 [MethodImpl(MethodImplOptions.AggressiveInlining)]
59 public static void ArgumentInRange(bool condition, string paramName) {
66 public static void ArgumentInRange(bool condition, string paramName) {
60 if (!condition)
67 if (!condition)
61 throw new ArgumentOutOfRangeException(paramName);
68 throw new ArgumentOutOfRangeException(paramName);
62 }
69 }
63
70
64 [MethodImpl(MethodImplOptions.AggressiveInlining)]
71 [MethodImpl(MethodImplOptions.AggressiveInlining)]
65 public static void ArgumentOfType(object value, Type type, string paramName) {
72 public static void ArgumentOfType(object value, Type type, string paramName) {
66 if (!type.IsInstanceOfType(value))
73 if (!type.IsInstanceOfType(value))
67 throw new ArgumentException(String.Format("The parameter must be of type {0}", type), paramName);
74 throw new ArgumentException(String.Format("The parameter must be of type {0}", type), paramName);
68 }
75 }
69
76
70 public static void Dispose(params IDisposable[] objects) {
77 public static void Dispose(params IDisposable[] objects) {
71 foreach (var d in objects)
78 foreach (var d in objects)
72 if (d != null)
79 if (d != null)
73 d.Dispose();
80 d.Dispose();
74 }
81 }
75
82
76 public static void Dispose(params object[] objects) {
83 public static void Dispose(params object[] objects) {
77 foreach (var obj in objects) {
84 foreach (var obj in objects) {
78 var d = obj as IDisposable;
85 var d = obj as IDisposable;
79 if (d != null)
86 if (d != null)
80 d.Dispose();
87 d.Dispose();
81 }
88 }
82 }
89 }
83
90
84 public static void DisposeCollection(IEnumerable<IDisposable> objects) {
91 public static void DisposeCollection(IEnumerable<IDisposable> objects) {
85 foreach (var d in objects)
92 foreach (var d in objects)
86 Dispose(d);
93 Dispose(d);
87 }
94 }
88
95
89 public static void DisposeCollection(IEnumerable objects) {
96 public static void DisposeCollection(IEnumerable objects) {
90 foreach (var d in objects)
97 foreach (var d in objects)
91 Dispose(d);
98 Dispose(d);
92 }
99 }
93
100
94 public static void Dispose(object obj) {
101 public static void Dispose(object obj) {
95 if (obj is IDisposable)
102 if (obj is IDisposable)
96 Dispose((IDisposable)obj);
103 Dispose((IDisposable)obj);
97
104
98 }
105 }
99
106
100 [DebuggerStepThrough]
107 [DebuggerStepThrough]
101 public static void DispatchEvent<T>(this EventHandler<T> handler, object sender, T args) {
108 public static void DispatchEvent<T>(this EventHandler<T> handler, object sender, T args) {
102 if (handler != null)
109 if (handler != null)
103 handler(sender, args);
110 handler(sender, args);
104 }
111 }
105
112
106 [DebuggerStepThrough]
113 [DebuggerStepThrough]
107 public static void DispatchEvent(this EventHandler handler, object sender, EventArgs args) {
114 public static void DispatchEvent(this EventHandler handler, object sender, EventArgs args) {
108 if (handler != null)
115 if (handler != null)
109 handler(sender, args);
116 handler(sender, args);
110 }
117 }
111
118
112 [DebuggerStepThrough]
119 [DebuggerStepThrough]
113 public static IPromise<T> Run<T>(Func<T> action) {
120 public static IPromise<T> Run<T>(Func<T> action) {
114 ArgumentNotNull(action, "action");
121 ArgumentNotNull(action, "action");
115
122
116 try {
123 try {
117 return Promise.Resolve(action());
124 return Promise.Resolve(action());
118 } catch (Exception err) {
125 } catch (Exception err) {
119 return Promise.Reject<T>(err);
126 return Promise.Reject<T>(err);
120 }
127 }
121 }
128 }
122
129
123 [DebuggerStepThrough]
130 [DebuggerStepThrough]
124 public static IPromise Run(Action action) {
131 public static IPromise Run(Action action) {
125 ArgumentNotNull(action, "action");
132 ArgumentNotNull(action, "action");
126
133
127 try {
134 try {
128 action();
135 action();
129 return Promise.Resolve();
136 return Promise.Resolve();
130 } catch (Exception err) {
137 } catch (Exception err) {
131 return Promise.Reject(err);
138 return Promise.Reject(err);
132 }
139 }
133 }
140 }
134
141
135 [DebuggerStepThrough]
142 [DebuggerStepThrough]
136 public static IPromise Run(Func<IPromise> action) {
143 public static IPromise Run(Func<IPromise> action) {
137 ArgumentNotNull(action, "action");
144 ArgumentNotNull(action, "action");
138
145
139 try {
146 try {
140 return action() ?? Promise.Reject(new Exception("The action returned null"));
147 return action() ?? Promise.Reject(new Exception("The action returned null"));
141 } catch (Exception err) {
148 } catch (Exception err) {
142 return Promise.Reject(err);
149 return Promise.Reject(err);
143 }
150 }
144 }
151 }
145
152
146 public static void NoWait(IPromise promise) {
153 public static void NoWait(IPromise promise) {
147 }
154 }
148
155
149 public static void NoWait(Task promise) {
156 public static void NoWait(Task promise) {
150 }
157 }
151
158
152 public static void NoWait<T>(Task<T> promise) {
159 public static void NoWait<T>(Task<T> promise) {
153 }
160 }
154
161
155 public static void Noop() {
162 public static void Noop() {
156 }
163 }
157
164
158 public static void Noop(CancellationToken ct) {
165 public static void Noop(CancellationToken ct) {
159 ct.ThrowIfCancellationRequested();
166 ct.ThrowIfCancellationRequested();
160 }
167 }
161
168
162 public static Task CreateTask() {
169 public static Task CreateTask() {
163 return new Task(Noop);
170 return new Task(Noop);
164 }
171 }
165
172
166 public static Task CreateTask(CancellationToken ct) {
173 public static Task CreateTask(CancellationToken ct) {
167 return new Task(Noop, ct);
174 return new Task(Noop, ct);
168 }
175 }
169
176
170 [DebuggerStepThrough]
177 [DebuggerStepThrough]
171 public static IPromise<T> Run<T>(Func<IPromise<T>> action) {
178 public static IPromise<T> Run<T>(Func<IPromise<T>> action) {
172 ArgumentNotNull(action, "action");
179 ArgumentNotNull(action, "action");
173
180
174 try {
181 try {
175 return action() ?? Promise.Reject<T>(new Exception("The action returned null"));
182 return action() ?? Promise.Reject<T>(new Exception("The action returned null"));
176 } catch (Exception err) {
183 } catch (Exception err) {
177 return Promise.Reject<T>(err);
184 return Promise.Reject<T>(err);
178 }
185 }
179 }
186 }
180
187
181 }
188 }
182 }
189 }
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