##// 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,10 +1,12
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
@@ -22,7 +24,11 namespace Implab.Playground {
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 }
@@ -49,8 +55,30 namespace Implab.Playground {
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
@@ -1,5 +1,6
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 -->
@@ -22,17 +23,18
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 }
@@ -27,8 +27,6 namespace Implab.ServiceHost.Unity
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 }
@@ -8,6 +8,7 namespace Implab.ServiceHost.Unity {
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
@@ -15,8 +16,6 namespace Implab.ServiceHost.Unity {
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) {
@@ -29,7 +28,22 namespace Implab.ServiceHost.Unity {
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
@@ -8,5 +8,9 namespace Implab.ServiceHost.Unity {
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 }
@@ -12,5 +12,8 namespace Implab.ServiceHost.Unity {
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 }
@@ -3,10 +3,17 using System.Xml.Serialization;
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 }
@@ -12,13 +12,17 namespace Implab.ServiceHost.Unity {
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 }
@@ -8,5 +8,9 namespace Implab.ServiceHost.Unity
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 }
@@ -24,6 +24,7 namespace Implab.ServiceHost.Unity
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 }
@@ -58,6 +59,10 namespace Implab.ServiceHost.Unity
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)) ),
@@ -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 }
@@ -55,6 +55,13 namespace Implab
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)
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