##// END OF EJS Templates
Refactoring...
cin -
r277:963b17c275be v3
parent child
Show More
@@ -0,0 +1,12
1 namespace Implab.ServiceHost.Unity {
2
3 /// <summary>
4 /// Базовый класс для элеметов контейнера.
5 /// </summary>
6 /// <remarks>
7 /// XmlSerializer требует использования классов при объявлении свойств, которые будут сериализованы <see cref="ContainerElement.Items"/>
8 /// </remarks>
9 public abstract class AbstractContainerItem {
10 public abstract void Visit(ContainerBuilder builder);
11 }
12 } No newline at end of file
@@ -0,0 +1,20
1 using System.Xml.Serialization;
2
3 namespace Implab.ServiceHost.Unity
4 {
5 public class ArrayParameterElement : InjectionParameterElement {
6
7 [XmlAttribute("itemsType")]
8 public string ItemsType { get; set; }
9
10 [XmlElement("dependency", typeof(DependencyParameterElement))]
11 [XmlElement("value", typeof(ValueParameterElement))]
12 [XmlElement("serialized", typeof(SerializedParameterElement))]
13 [XmlElement("default", typeof(DefaultParameterElement))]
14 public InjectionParameterElement[] Items { get; set; }
15
16 public override void Visit(InjectionValueBuilder builder) {
17 builder.Visit(this);
18 }
19 }
20 } No newline at end of file
@@ -0,0 +1,11
1 namespace Implab.ServiceHost.Unity {
2 public class FactoryAbstractRegistratrion : AbstractRegistration {
3 public override void Visit(ContainerBuilder builder) {
4 builder.Visit(this);
5 }
6
7 public virtual void Visit(FactoryRegistrationBuilder builder) {
8 base.Visit(builder);
9 }
10 }
11 } No newline at end of file
@@ -0,0 +1,36
1 using System;
2 using Implab.Components;
3 using Unity;
4 using Unity.Injection;
5 using Unity.Registration;
6
7 namespace Implab.ServiceHost.Unity
8 {
9 public class FactoryRegistrationBuilder : RegistrationBuilder {
10
11 internal InjectionMember Factory { get; private set; }
12
13 internal FactoryRegistrationBuilder(Type registrationType) : base(registrationType) {
14 }
15
16 public void SetFactoryDelegate(Delegate factory) {
17 Safe.ArgumentNotNull(factory, nameof(factory));
18
19 Factory = new DelegateInjectionFactory(factory);
20 }
21
22 public void SetFactoryDependency<T>(string dependencyName, Func<T, object> factory) {
23 Safe.ArgumentNotNull(factory, nameof(factory));
24
25 Factory = new InjectionFactory((c,t,name) => {
26 var backend = c.Resolve<T>(dependencyName);
27 return factory(backend);
28 });
29 }
30
31 public void SetFactoryDependency<TFac, TObj>(string dependencyName) where TFac : IFactory<TObj> {
32
33 Factory = new InjectionFactory(c => c.Resolve<TFac>(dependencyName).Create());
34 }
35 }
36 } No newline at end of file
@@ -0,0 +1,12
1 namespace Implab.ServiceHost.Unity
2 {
3 public abstract class InstanceAbstractRegistration : AbstractRegistration {
4 public override void Visit(ContainerBuilder builder) {
5 builder.Visit(this);
6 }
7
8 public virtual void Visit(InstanceRegistrationBuilder builder) {
9 base.Visit(builder);
10 }
11 }
12 } No newline at end of file
@@ -0,0 +1,13
1 using System;
2
3 namespace Implab.ServiceHost.Unity
4 {
5 public class InstanceRegistrationBuilder : RegistrationBuilder {
6
7 public InjectionValueBuilder ValueBuilder { get; private set; }
8
9 internal InstanceRegistrationBuilder(TypeResolver typeResolver, Type registrationType) : base(registrationType) {
10 ValueBuilder = new InjectionValueBuilder(typeResolver, registrationType);
11 }
12 }
13 } No newline at end of file
@@ -0,0 +1,17
1 using System;
2
3 namespace Implab.ServiceHost.Unity
4 {
5 public abstract class TypeAbstractRegistration : AbstractRegistration {
6
7 public abstract Type GetImplementationType(Func<string,Type> resolver);
8
9 override public void Visit(ContainerBuilder builder) {
10 builder.Visit(this);
11 }
12
13 public virtual void Visit(TypeRegistrationBuilder builder) {
14 base.Visit(builder);
15 }
16 }
17 } No newline at end of file
@@ -1,95 +1,114
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Diagnostics;
3 using System.Diagnostics;
3 using System.Linq;
4 using System.Linq;
4 using Implab.Diagnostics;
5 using Implab.Diagnostics;
5 using Implab.ServiceHost.Unity;
6 using Implab.ServiceHost.Unity;
6 using Implab.Xml;
7 using Implab.Xml;
7 using Unity;
8 using Unity;
8 using Unity.Injection;
9 using Unity.Injection;
9 using Unity.Registration;
10 using Unity.Registration;
10
11
11 namespace Implab.Playground {
12 namespace Implab.Playground {
12
13
13 public class Foo {
14 public class Foo {
14
15
15 public class Bar {
16 public class Bar {
16
17
17 }
18 }
18
19
19 public string Name { get; set; }
20 public string Name { get; set; }
20
21
21 public int IntValue { get; set; }
22 public int IntValue { get; set; }
22
23
23 public string StringValue { get; set; }
24 public string StringValue { get; set; }
24
25
26 public void AddRange(Foo[] items) {
27 Console.WriteLine($"AddRange: Foo[]");
28 }
29
25 }
30 }
26
31
27 public interface IContainer<T> {
32 public interface IContainer<T> {
28 T Instance { get; set; }
33 T Instance { get; set; }
29 }
34 }
30
35
31 public class Container<T> : IContainer<T> {
36 public class Container<T> : IContainer<T> {
32 public Container() {
37 public Container() {
33
38
34 }
39 }
35
40
36 public Container(T instance) {
41 public Container(T instance) {
37 Instance = instance;
42 Instance = instance;
38 }
43 }
39
44
40 public T Instance { get; set; }
45 public T Instance { get; set; }
41
46
42 public void SetInstance(T value) {
47 public void SetInstance(T value) {
43 Instance = value;
48 Instance = value;
44 }
49 }
50
51 public void AddRange(List<T> items) {
52 Console.WriteLine($"AddRange: {typeof(List<T>)}");
53 }
54
55 public void AddRange(T[] items) {
56 Console.WriteLine($"AddRange: T[] ofType {typeof(T[])}");
57 }
45 }
58 }
46
59
47 public class Program {
60 public class Program {
48
61
49 static void Main(string[] args) {
62 static void Main(string[] args) {
63 var listener = new SimpleTraceListener(Console.Out);
64 var source = Trace<TypeResolver>.TraceSource;
65 source.Switch.Level = SourceLevels.All;
66 source.Listeners.Add(listener);
67
50 var stopwatch = new Stopwatch();
68 var stopwatch = new Stopwatch();
51 stopwatch.Start();
69 stopwatch.Start();
52
70
53 var ctx = new ContainerBuilder();
71 var ctx = new ContainerBuilder();
54
72
55 Console.WriteLine($"Created: {stopwatch.ElapsedMilliseconds}");
73 Console.WriteLine($"Created: {stopwatch.ElapsedMilliseconds}");
56
74 stopwatch.Restart();
75
57 ctx.LoadConfig("data/sample.xml");
76 ctx.LoadConfig("data/sample.xml");
58
77
59 Console.WriteLine($"Loaded: {stopwatch.ElapsedMilliseconds}");
78 Console.WriteLine($"Loaded: {stopwatch.ElapsedMilliseconds}");
60
79
61 var container = ctx.Container;
80 var container = ctx.Container;
62
81
63
82 stopwatch.Restart();
64
65 var instace1 = container.Resolve<IContainer<string>>();
83 var instace1 = container.Resolve<IContainer<string>>();
66 Console.WriteLine($"Resolved1: {stopwatch.ElapsedMilliseconds}");
84 Console.WriteLine($"Resolved1: {stopwatch.ElapsedMilliseconds}");
85
86 stopwatch.Restart();
67 var instace2 = container.Resolve<IContainer<Foo>>();
87 var instace2 = container.Resolve<IContainer<Foo>>();
68
69 Console.WriteLine($"Resolved2: {stopwatch.ElapsedMilliseconds}");
88 Console.WriteLine($"Resolved2: {stopwatch.ElapsedMilliseconds}");
70
89
71 DisplayContainerRegistrations(container);
90 DisplayContainerRegistrations(container);
72 }
91 }
73
92
74 static void DisplayContainerRegistrations(IUnityContainer theContainer) {
93 static void DisplayContainerRegistrations(IUnityContainer theContainer) {
75 string regName, regType, mapTo, lifetime;
94 string regName, regType, mapTo, lifetime;
76 Console.WriteLine("Container has {0} Registrations:",
95 Console.WriteLine("Container has {0} Registrations:",
77 theContainer.Registrations.Count());
96 theContainer.Registrations.Count());
78 foreach (ContainerRegistration item in theContainer.Registrations) {
97 foreach (ContainerRegistration item in theContainer.Registrations) {
79 regType = item.RegisteredType.FullName;
98 regType = item.RegisteredType.FullName;
80 mapTo = item.MappedToType.FullName;
99 mapTo = item.MappedToType.FullName;
81 regName = item.Name ?? "[default]";
100 regName = item.Name ?? "[default]";
82 lifetime = item.LifetimeManager.LifetimeType.Name;
101 lifetime = item.LifetimeManager.LifetimeType.Name;
83 if (mapTo != regType) {
102 if (mapTo != regType) {
84 mapTo = " -> " + mapTo;
103 mapTo = " -> " + mapTo;
85 } else {
104 } else {
86 mapTo = string.Empty;
105 mapTo = string.Empty;
87 }
106 }
88 lifetime = lifetime.Substring(0, lifetime.Length - "LifetimeManager".Length);
107 lifetime = lifetime.Substring(0, lifetime.Length - "LifetimeManager".Length);
89 Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo, regName, lifetime);
108 Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo, regName, lifetime);
90 }
109 }
91 }
110 }
92
111
93
112
94 }
113 }
95 }
114 }
@@ -1,49 +1,68
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="System"/>
4 <namespace name="System.Collections.Generic"/>
4 <namespace name="Implab.Playground"/>
5 <namespace name="Implab.Playground"/>
5
6
6 <!-- foo1 -->
7 <!-- foo1 -->
7 <register name="foo1" type="Foo">
8 <register name="foo1" type="Foo">
8 <property name="Name">
9 <property name="Name">
9 <value>FOO!</value>
10 <value>FOO!</value>
10 </property>
11 </property>
11 </register>
12 </register>
12
13
13 <!-- foo2 -->
14 <!-- foo2 -->
14 <register name="foo2" type="Foo">
15 <register name="foo2" type="Foo">
15 <property name="Name">
16 <property name="Name">
16 <value>GOOD</value>
17 <value>GOOD</value>
17 </property>
18 </property>
18 <property name="IntValue">
19 <property name="IntValue">
19 <value>2</value>
20 <value>2</value>
20 </property>
21 </property>
21 </register>
22 </register>
22
23
23 <register type="Foo">
24 <register type="Foo">
25 <method name="AddRange">
26 <array itemsType="Foo">
27 <dependency name="foo2"/>
28 </array>
29 </method>
24 </register>
30 </register>
25
31
26 <register type="IContainer{}" mapTo="Container{}">
32 <register type="IContainer{}" mapTo="Container{}">
27 <constructor/>
33 <constructor/>
28 <method name="SetInstance">
34 <method name="SetInstance">
29 <dependency type="T"/>
35 <dependency type="T"/>
30 </method>
36 </method>
37 <method name="AddRange">
38 <array itemsType="T">
39 <dependency name="foo2"/>
40 </array>
41 </method>
42 </register>
43
44 <register type="List{}">
45 <constructor />
31 </register>
46 </register>
32
47
33 <register type="IContainer{String}" mapTo="Container{String}">
48 <register type="IContainer{String}" mapTo="Container{String}">
34 <constructor/>
49 <constructor/>
35 <method name="SetInstance">
50 <method name="SetInstance">
36 <dependency type="String" name="name1"/>
51 <dependency type="String" name="name1"/>
37 </method>
52 </method>
38 </register>
53 </register>
39
54
40 <serialized type="Foo+Bar">
55 <serialized type="Foo+Bar">
41 <Bar xmlns="" id="1">
56 <Bar xmlns="" id="1">
42 <Name>Baaar</Name>
57 <Name>Baaar</Name>
43 </Bar>
58 </Bar>
44 </serialized>
59 </serialized>
45
60
46 <value name="connection1" type="String"><![CDATA[Connect me <here>!]]></value>
61 <value name="connection1" type="String"><![CDATA[Connect me <here>!]]></value>
47 <value name="name1" type="String" value="Hello!"/>
62 <value name="name1" type="String" value="Hello!"/>
48
63
64 <factory name="foo3" type="FooFactory">
65 <parameter name="FooName"><![CDATA[Wired "" objecty <> name @#$%^&]]></parameter>
66 </factory>
67
49 </container> No newline at end of file
68 </container>
@@ -1,10 +1,10
1 using System;
1 using System;
2
2
3 namespace Implab.ServiceHost.Unity {
3 namespace Implab.ServiceHost.Unity {
4 /// <summary>
4 /// <summary>
5 /// Base class for injections, each injection is applied to the type registration context.
5 /// Base class for injections, each injection is applied to the type registration context.
6 /// </summary>
6 /// </summary>
7 public abstract class AbstractInjectionElement {
7 public abstract class AbstractMemberInjection {
8 internal abstract void Visit(TypeRegistrationBuilder context);
8 internal abstract void Visit(TypeRegistrationBuilder context);
9 }
9 }
10 } No newline at end of file
10 }
@@ -1,31 +1,42
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 : ContainerItemElement {
8 /// <summary>
9 /// Базовая информаци о регистрации в контейнере: тип, имя и время жизни
10 /// </summary>
11 public abstract class AbstractRegistration : AbstractContainerItem {
9
12
10 /// <summary>
13 /// <summary>
11 /// An optional name for a registration in the container
14 /// An optional name for a registration in the container
12 /// </summary>
15 /// </summary>
13 [XmlAttribute("name")]
16 [XmlAttribute("name")]
14 public string Name {
17 public string Name {
15 get; set;
18 get; set;
16 }
19 }
17
20
18 [XmlElement("signleton", typeof(SimgletonLifetimeElement))]
21 [XmlElement("signleton", typeof(SingletonLifetimeElement))]
19 [XmlElement("context", typeof(ContextLifetimeElement))]
22 [XmlElement("context", typeof(ContextLifetimeElement))]
20 [XmlElement("container", typeof(ContainerLifetimeElement))]
23 [XmlElement("container", typeof(ContainerLifetimeElement))]
21 [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
24 [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
22 public LifetimeElement Lifetime {get; set;}
25 public LifetimeElement Lifetime {get; set;}
23
26
24 /// <summary>
27 /// <summary>
25 /// A type specification for the service registration,
28 /// A type specification for the service registration,
26 /// </summary>
29 /// </summary>
27 [XmlAttribute("type")]
30 [XmlAttribute("type")]
28 public string RegistrationType { get; set; }
31 public string RegistrationType { get; set; }
29
32
33 public virtual Type GetRegistrationType(Func<string,Type> resolver) {
34 return resolver(RegistrationType);
35 }
36
37 public virtual void Visit(RegistrationBuilder builder) {
38 Lifetime?.Visit(builder);
39 }
40
30 }
41 }
31 } No newline at end of file
42 }
@@ -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 : ContainerItemElement {
6 public class AssemblyElement : AbstractContainerItem {
7 [XmlAttribute("name")]
7 [XmlAttribute("name")]
8 public string AssemblyName { get; set; }
8 public string AssemblyName { get; set; }
9
9
10 public override void Visit(ContainerBuilder context) {
10 public override void Visit(ContainerBuilder builder) {
11 context.Visit(this);
11 builder.Visit(this);
12 }
12 }
13 }
13 }
14 } No newline at end of file
14 }
@@ -1,16 +1,17
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 : AbstractMemberInjection {
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 [XmlElement("array", typeof(ArrayParameterElement))]
10 public InjectionParameterElement[] Parameters { get; set; }
11 public InjectionParameterElement[] Parameters { get; set; }
11
12
12 internal override void Visit(TypeRegistrationBuilder context) {
13 internal override void Visit(TypeRegistrationBuilder context) {
13 context.Visit(this);
14 context.Visit(this);
14 }
15 }
15 }
16 }
16 } No newline at end of file
17 }
@@ -1,125 +1,118
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 global::Unity.Registration;
12 using Implab.Xml;
12 using Implab.Xml;
13 using static Trace<ContainerBuilder>;
13 using static Trace<ContainerBuilder>;
14
14
15 public class ContainerBuilder {
15 public class ContainerBuilder {
16
16
17 readonly TypeResolver m_resolver;
17 readonly TypeResolver m_resolver;
18
18
19 readonly UnityContainer m_container;
19 readonly UnityContainer m_container;
20
20
21 readonly ContainerConfigurationSchema m_schema;
21 readonly ContainerConfigurationSchema m_schema;
22
22
23 public UnityContainer Container {
23 public UnityContainer Container {
24 get {
24 get {
25 return m_container;
25 return m_container;
26 }
26 }
27 }
27 }
28
28
29 public ContainerBuilder() : this(null, null) {
29 public ContainerBuilder() : this(null, null) {
30 }
30 }
31
31
32 public ContainerBuilder(UnityContainer container, ContainerConfigurationSchema schema) {
32 public ContainerBuilder(UnityContainer container, ContainerConfigurationSchema schema) {
33 m_container = container ?? new UnityContainer();
33 m_container = container ?? new UnityContainer();
34 m_resolver = new TypeResolver();
34 m_resolver = new TypeResolver();
35 m_schema = schema ?? ContainerConfigurationSchema.Default;
35 m_schema = schema ?? ContainerConfigurationSchema.Default;
36 }
36 }
37
37
38 public Type ResolveType(string typeReference) {
38 public Type ResolveType(string typeReference) {
39 return m_resolver.Resolve(typeReference);
39 return m_resolver.Resolve(typeReference);
40 }
40 }
41
41
42 internal void Visit(RegisterElement registerElement) {
42
43 var registrationType = ResolveType(registerElement.RegistrationType);
43 internal void Visit(TypeAbstractRegistration typeRegistration) {
44 var implementationType = string.IsNullOrEmpty(registerElement.MapToType) ? registrationType : ResolveType(registerElement.MapToType);
44 var registrationType = typeRegistration.GetRegistrationType(ResolveType);
45 var implementationType = typeRegistration.GetImplementationType(ResolveType) ?? registrationType;
45
46
46 var registrationContext = new TypeRegistrationBuilder(
47 var registrationContext = new TypeRegistrationBuilder(
47 m_resolver,
48 m_resolver,
48 registrationType,
49 registrationType,
49 implementationType
50 implementationType
50 );
51 );
51
52
52 if (registerElement.Injectors != null) {
53 typeRegistration.Visit(registrationContext);
53 foreach (var injector in registerElement.Injectors) {
54 injector.Visit(registrationContext);
55 }
56 }
57
54
58 m_container.RegisterType(
55 m_container.RegisterType(
59 registrationContext.RegistrationType,
56 registrationContext.RegistrationType,
60 registrationContext.ImplementationType,
57 registrationContext.ImplementationType,
61 registerElement.Name,
58 typeRegistration.Name,
62 registerElement.Lifetime?.GetLifetimeManager(this),
59 registrationContext.Lifetime,
63 registrationContext.Injections
60 registrationContext.Injections
64 );
61 );
65 }
62 }
66
63
67 internal void Visit(SerializedElement serializedElement) {
64 internal void Visit(InstanceAbstractRegistration instanceRegistration) {
68 var registrationType = ResolveType(serializedElement.RegistrationType);
65 var registrationType = instanceRegistration.GetRegistrationType(ResolveType);
69 var valueBuilder = new InjectionValueBuilder(m_resolver, null);
66
67 var builder = new InstanceRegistrationBuilder(m_resolver, registrationType);
70
68
71 valueBuilder.Visit(serializedElement);
69 instanceRegistration.Visit(builder);
72
70
73 m_container.RegisterInstance(
71 m_container.RegisterInstance(
74 registrationType,
72 builder.ValueBuilder.ValueType,
75 serializedElement.Name,
73 instanceRegistration.Name,
76 valueBuilder.Value,
74 builder.ValueBuilder.Value,
77 serializedElement.Lifetime?.GetLifetimeManager(this)
75 builder.Lifetime
78 );
76 );
79 }
77 }
80
78
81 internal void Visit(ValueElement valueElement) {
79 internal void Visit(FactoryAbstractRegistratrion factoryRgistration) {
82 var registrationType = ResolveType(valueElement.RegistrationType);
80 var registrationType = factoryRgistration.GetRegistrationType(ResolveType);
83 var valueBuilder = new InjectionValueBuilder(m_resolver, null);
81
82 var builder = new FactoryRegistrationBuilder(registrationType);
84
83
85 valueBuilder.Visit(valueElement);
84 factoryRgistration.Visit(builder);
86
85
87 m_container.RegisterInstance(
86 m_container.RegisterType(
88 registrationType,
87 builder.RegistrationType,
89 valueElement.Name,
88 factoryRgistration.Name,
90 valueBuilder.Value,
89 builder.Lifetime,
91 valueElement.Lifetime?.GetLifetimeManager(this)
90 builder.Factory
92 );
91 );
93 }
92 }
94
93
95 internal void Visit(NamespaceElement namespaceElement) {
94 internal void Visit(NamespaceElement namespaceElement) {
96 m_resolver.AddNamespace(namespaceElement.Name);
95 m_resolver.AddNamespace(namespaceElement.Name);
97 }
96 }
98
97
99 internal void Visit(AssemblyElement assemblyElement) {
98 internal void Visit(AssemblyElement assemblyElement) {
100 Assembly.Load(assemblyElement.AssemblyName);
99 Assembly.Load(assemblyElement.AssemblyName);
101 }
100 }
102
101
103 internal void Visit(IncludeElement includeElement) {
102 internal void Visit(IncludeElement includeElement) {
104 Include(includeElement.Href);
103 Include(includeElement.Href);
105 }
104 }
106
105
107 public void Include(string file) {
106 public void Include(string file) {
108 var includeContext = new ContainerBuilder(m_container, m_schema);
107 var includeContext = new ContainerBuilder(m_container, m_schema);
109 includeContext.LoadConfig(file);
108 includeContext.LoadConfig(file);
110 }
109 }
111
110
112 public void LoadConfig(string file) {
111 public void LoadConfig(string file) {
113 var config = m_schema.LoadFile(file);
112 var config = m_schema.LoadFile(file);
114 Visit(config);
113
114 config.Visit(this);
115 }
115 }
116
116
117 internal void Visit(ContainerElement containerElement) {
118 foreach (var item in containerElement.Items)
119 item.Visit(this);
120 }
121
122
123
124 }
117 }
125 } No newline at end of file
118 }
@@ -1,69 +1,69
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.IO;
3 using System.IO;
4 using System.Reflection;
4 using System.Reflection;
5 using System.Xml;
5 using System.Xml;
6 using System.Xml.Serialization;
6 using System.Xml.Serialization;
7 using Implab.Components;
7 using Implab.Components;
8
8
9 namespace Implab.ServiceHost.Unity {
9 namespace Implab.ServiceHost.Unity {
10 public class ContainerConfigurationSchema {
10 public class ContainerConfigurationSchema {
11
11
12 public static ContainerConfigurationSchema Default { get; private set; } = CreateDefault();
12 public static ContainerConfigurationSchema Default { get; private set; } = CreateDefault();
13
13
14 readonly LazyAndWeak<XmlSerializer> m_seralizer;
14 readonly LazyAndWeak<XmlSerializer> m_seralizer;
15
15
16 readonly XmlAttributeOverrides m_overrides = new XmlAttributeOverrides();
16 readonly XmlAttributeOverrides m_overrides = new XmlAttributeOverrides();
17
17
18 readonly XmlAttributes m_containerItems = new XmlAttributes();
18 readonly XmlAttributes m_containerItems = new XmlAttributes();
19
19
20 public XmlSerializer Serializer {
20 public XmlSerializer Serializer {
21 get {
21 get {
22 return m_seralizer.Value;
22 return m_seralizer.Value;
23 }
23 }
24 }
24 }
25
25
26 public ContainerConfigurationSchema() {
26 public ContainerConfigurationSchema() {
27 m_overrides.Add(typeof(ContainerElement), nameof(ContainerElement.Items), m_containerItems);
27 m_overrides.Add(typeof(ContainerElement), nameof(ContainerElement.Items), m_containerItems);
28
28
29 m_seralizer = new LazyAndWeak<XmlSerializer>(() => new XmlSerializer(typeof(ContainerElement), m_overrides));
29 m_seralizer = new LazyAndWeak<XmlSerializer>(() => new XmlSerializer(typeof(ContainerElement), m_overrides));
30 }
30 }
31
31
32 public void RegisterContainerElement(Type type, string name) {
32 public void RegisterContainerElement(Type type, string name) {
33 Safe.ArgumentNotNull(type, nameof(type));
33 Safe.ArgumentNotNull(type, nameof(type));
34 Safe.ArgumentNotEmpty(name, nameof(name));
34 Safe.ArgumentNotEmpty(name, nameof(name));
35
35
36 if(!type.IsSubclassOf(typeof(ContainerItemElement)))
36 if(!type.IsSubclassOf(typeof(AbstractContainerItem)))
37 throw new Exception($"RegisterContainerElement '{name}': {type} must be subclass of {typeof(ContainerItemElement)}");
37 throw new Exception($"RegisterContainerElement '{name}': {type} must be subclass of {typeof(AbstractContainerItem)}");
38
38
39 m_containerItems.XmlElements.Add(
39 m_containerItems.XmlElements.Add(
40 new XmlElementAttribute(name, type)
40 new XmlElementAttribute(name, type)
41 );
41 );
42 }
42 }
43
43
44 public void RegisterContainerElement<T>(string name) where T : ContainerItemElement {
44 public void RegisterContainerElement<T>(string name) where T : AbstractContainerItem {
45 RegisterContainerElement(typeof(T), name);
45 RegisterContainerElement(typeof(T), name);
46 }
46 }
47
47
48 public ContainerElement LoadFile(string file) {
48 public ContainerElement LoadFile(string file) {
49 using (var reader = XmlReader.Create(file)) {
49 using (var reader = XmlReader.Create(file)) {
50 return (ContainerElement)Serializer.Deserialize(reader);
50 return (ContainerElement)Serializer.Deserialize(reader);
51 }
51 }
52 }
52 }
53
53
54 static ContainerConfigurationSchema CreateDefault() {
54 static ContainerConfigurationSchema CreateDefault() {
55 var schema = new ContainerConfigurationSchema();
55 var schema = new ContainerConfigurationSchema();
56
56
57 schema.RegisterContainerElement<RegisterElement>("register");
57 schema.RegisterContainerElement<RegisterElement>("register");
58 schema.RegisterContainerElement<SerializedElement>("serialized");
58 schema.RegisterContainerElement<SerializedElement>("serialized");
59 schema.RegisterContainerElement<ValueElement>("value");
59 schema.RegisterContainerElement<ValueElement>("value");
60 schema.RegisterContainerElement<IncludeElement>("include");
60 schema.RegisterContainerElement<IncludeElement>("include");
61 schema.RegisterContainerElement<AssemblyElement>("assembly");
61 schema.RegisterContainerElement<AssemblyElement>("assembly");
62 schema.RegisterContainerElement<NamespaceElement>("namespace");
62 schema.RegisterContainerElement<NamespaceElement>("namespace");
63
63
64 return schema;
64 return schema;
65 }
65 }
66
66
67
67
68 }
68 }
69 } No newline at end of file
69 }
@@ -1,17 +1,19
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 : ContainerItemElement {
9 public class ContainerElement : AbstractContainerItem {
10
10
11 public List<ContainerItemElement> Items { get; set; } = new List<ContainerItemElement>();
11 public List<AbstractContainerItem> Items { get; set; } = new List<AbstractContainerItem>();
12
12
13 public override void Visit(ContainerBuilder context) {
13 public override void Visit(ContainerBuilder context) {
14 context.Visit(this);
14 if (Items != null)
15 foreach(var item in Items)
16 item.Visit(context);
15 }
17 }
16 }
18 }
17 } No newline at end of file
19 }
@@ -1,10 +1,10
1 using Unity.Lifetime;
1 using Unity.Lifetime;
2
2
3 namespace Implab.ServiceHost.Unity
3 namespace Implab.ServiceHost.Unity
4 {
4 {
5 public class ContainerLifetimeElement : LifetimeElement {
5 public class ContainerLifetimeElement : LifetimeElement {
6 public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
6 public override void Visit(RegistrationBuilder builder) {
7 return new ContainerControlledLifetimeManager();
7 builder.Visit(this);
8 }
8 }
9 }
9 }
10 } No newline at end of file
10 }
@@ -1,10 +1,10
1 using Unity.Lifetime;
1 using Unity.Lifetime;
2
2
3 namespace Implab.ServiceHost.Unity
3 namespace Implab.ServiceHost.Unity
4 {
4 {
5 public class ContextLifetimeElement : LifetimeElement {
5 public class ContextLifetimeElement : LifetimeElement {
6 public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
6 public override void Visit(RegistrationBuilder builder) {
7 return new PerResolveLifetimeManager();
7 builder.Visist(this);
8 }
8 }
9 }
9 }
10 } No newline at end of file
10 }
@@ -1,12 +1,13
1 namespace Implab.ServiceHost.Unity
1 namespace Implab.ServiceHost.Unity
2 {
2 {
3 public class DefaultParameterElement : InjectionParameterElement, ITextValue {
3 public class DefaultParameterElement : InjectionParameterElement {
4 public string Value {
4 public string Value {
5 get { return null; }
5 get { return null; }
6 }
6 }
7
7
8 public override void Visit(InjectionValueBuilder builder) {
8 public override void Visit(InjectionValueBuilder builder) {
9 builder.Visit(this);
9 var type = builder.ResolveInjectedValueType(TypeName);
10 builder.SetValue(type, Safe.CreateDefaultValue(type));
10 }
11 }
11 }
12 }
12 } No newline at end of file
13 }
@@ -1,16 +1,17
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 DependencyParameterElement : InjectionParameterElement, IDependencyReference {
4 public class DependencyParameterElement : InjectionParameterElement {
5
5
6 [XmlAttribute("name")]
6 [XmlAttribute("name")]
7 public string DependencyName { get; set; }
7 public string DependencyName { get; set; }
8
8
9 [XmlAttribute("optional")]
9 [XmlAttribute("optional")]
10 public bool Optional { get; set; }
10 public bool Optional { get; set; }
11
11
12 public override void Visit(InjectionValueBuilder builder) {
12 public override void Visit(InjectionValueBuilder builder) {
13 builder.Visit(this);
13 var type = builder.ResolveInjectedValueType(TypeName);
14 builder.SetDependencyReference(type, DependencyName, Optional);
14 }
15 }
15 }
16 }
16 } No newline at end of file
17 }
@@ -1,10 +1,10
1 using Unity.Lifetime;
1 using Unity.Lifetime;
2
2
3 namespace Implab.ServiceHost.Unity
3 namespace Implab.ServiceHost.Unity
4 {
4 {
5 public class HierarchicalLifetimeElement : LifetimeElement {
5 public class HierarchicalLifetimeElement : LifetimeElement {
6 public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
6 public override void Visit(RegistrationBuilder builder) {
7 return new HierarchicalLifetimeManager();
7 builder.Visit(this);
8 }
8 }
9 }
9 }
10 } No newline at end of file
10 }
@@ -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 : ContainerItemElement {
5 public class IncludeElement : AbstractContainerItem {
6 [XmlAttribute("href")]
6 [XmlAttribute("href")]
7 public string Href { get; set; }
7 public string Href { get; set; }
8
8
9 public override void Visit(ContainerBuilder context) {
9 public override void Visit(ContainerBuilder context) {
10 context.Visit(this);
10 context.Visit(this);
11 }
11 }
12 }
12 }
13 } No newline at end of file
13 }
@@ -1,12 +1,12
1 using System;
1 using System;
2 using System.Xml.Serialization;
2 using System.Xml.Serialization;
3
3
4 namespace Implab.ServiceHost.Unity {
4 namespace Implab.ServiceHost.Unity {
5 public abstract class InjectionParameterElement : IInjectionParameter {
5 public abstract class InjectionParameterElement {
6
6
7 [XmlAttribute("type")]
7 [XmlAttribute("type")]
8 public string TypeName { get; set; }
8 public string TypeName { get; set; }
9
9
10 public abstract void Visit(InjectionValueBuilder builder);
10 public abstract void Visit(InjectionValueBuilder builder);
11 }
11 }
12 } No newline at end of file
12 }
@@ -1,64 +1,89
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.ComponentModel;
3 using System.ComponentModel;
4 using System.Linq;
3 using System.Xml.Serialization;
5 using System.Xml.Serialization;
4 using Unity.Injection;
6 using Unity.Injection;
5
7
6 namespace Implab.ServiceHost.Unity {
8 namespace Implab.ServiceHost.Unity {
7
9
8 public class InjectionValueBuilder {
10 public class InjectionValueBuilder {
9
11
10 readonly TypeResolver m_resolver;
12 readonly TypeResolver m_resolver;
11
13
12 public Type DefaultType { get; private set; }
14 public Type DefaultType { get; private set; }
13
15
14 public Type ValueType { get; set; }
16 public Type ValueType { get; private set; }
15
17
16 public object Value { get; set; }
18 public object Value { get; set; }
17
19
18 public InjectionParameterValue Injection {
20 internal InjectionParameterValue Injection {
19 get {
21 get {
20 if (Value != null)
22 if (Value != null)
21 return InjectionParameterValue.ToParameter(Value);
23 return InjectionParameterValue.ToParameter(Value);
22
24
23 return new InjectionParameter(ValueType, null);
25 return new InjectionParameter(ValueType, null);
24 }
26 }
25 }
27 }
26
28
27 internal InjectionValueBuilder(TypeResolver resolver, Type acceptsType) {
29 internal InjectionValueBuilder(TypeResolver resolver, Type defaultType) {
28 m_resolver = resolver;
30 m_resolver = resolver;
29 DefaultType = acceptsType;
31 DefaultType = defaultType;
30 }
32 }
31
33
32 public Type ResolveType(string typeSpec) {
34 public Type ResolveInjectedValueType(string typeSpec) {
33 if (string.IsNullOrEmpty(typeSpec)) {
35 if (string.IsNullOrEmpty(typeSpec)) {
34 if (DefaultType == null)
36 if (DefaultType == null)
35 throw new Exception("The type must be specified");
37 throw new Exception("The type must be specified");
36 return DefaultType;
38 return DefaultType;
37 }
39 }
38 return m_resolver.Resolve(typeSpec);
40 return m_resolver.Resolve(typeSpec);
39 }
41 }
40
42
41 public void Visit(ITextValue value) {
43 public Type ResolveType(string typeSpec) {
42 ValueType = ResolveType(value.TypeName);
44 return m_resolver.Resolve(typeSpec);
45 }
43
46
44 Value = string.IsNullOrEmpty(value.Value) ?
47 public void SetValue(Type type, object value) {
45 Safe.CreateDefaultValue(ValueType) :
48 ValueType = type;
46 TypeDescriptor.GetConverter(ValueType).ConvertFromString(value.Value);
49 Value = value;
50 }
51
52 public void SetValue<T>(T value) {
53 SetValue(typeof(T), value);
54 }
55
56 public void SetDependencyReference(Type type, string name, bool optional) {
57 ValueType = type;
58 Value = optional ? (object)new OptionalParameter(type, name) : new ResolvedParameter(type, name);
47 }
59 }
48
60
49 public void Visit(ISerializedValue value) {
61 internal void Visit(ArrayParameterElement arrayParameter) {
50 ValueType = ResolveType(value.TypeName);
62 Type itemsType = null;
63 var arrayType = string.IsNullOrEmpty(arrayParameter.TypeName) ? null : ResolveType(arrayParameter.TypeName);
51
64
52 var serializer = new XmlSerializer(ValueType);
65 if (!string.IsNullOrEmpty(arrayParameter.ItemsType)) {
66 itemsType = ResolveType(arrayParameter.ItemsType);
67 if (arrayType == null)
68 arrayType = itemsType.MakeArrayType();
69 } else {
70 itemsType = arrayType?.GetInterface(typeof(IEnumerable<>).FullName)?.GetGenericArguments()[0];
71 }
53
72
54 using (var reader = value.GetReader())
73 if (itemsType == null)
55 Value = new InjectionParameter(ValueType, serializer.Deserialize(reader));
74 throw new Exception("Failed to determine array elements type");
56 }
57
75
58 public void Visit(IDependencyReference value) {
76 InjectionParameterValue[] injections = (arrayParameter.Items ?? new InjectionParameterElement[0])
59 ValueType = ResolveType(value.TypeName);
77 .Select(x => {
60 Value = new ResolvedParameter(ValueType, value.DependencyName);
78 var builder = new InjectionValueBuilder(m_resolver, itemsType);
79 x.Visit(builder);
80 return builder.Injection;
81 })
82 .ToArray();
83
84 var array = itemsType.IsGenericParameter ? (object)new GenericResolvedArrayParameter(itemsType.Name, injections) : new ResolvedArrayParameter(itemsType, injections);
85 ValueType = arrayType;
86 Value = array;
61 }
87 }
62
63 }
88 }
64 } No newline at end of file
89 }
@@ -1,10 +1,5
1 using Unity.Lifetime;
1 namespace Implab.ServiceHost.Unity {
2
2 public abstract class LifetimeElement {
3 namespace Implab.ServiceHost.Unity
3 public abstract void Visit(RegistrationBuilder builder);
4 {
5 public abstract class LifetimeElement
6 {
7 public abstract LifetimeManager GetLifetimeManager(ContainerBuilder ctx);
8
9 }
4 }
10 } No newline at end of file
5 }
@@ -1,19 +1,20
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 : AbstractMemberInjection {
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 [XmlElement("array", typeof(ArrayParameterElement))]
13 public InjectionParameterElement[] Parameters { get; set; }
14 public InjectionParameterElement[] Parameters { get; set; }
14
15
15 internal override void Visit(TypeRegistrationBuilder context) {
16 internal override void Visit(TypeRegistrationBuilder context) {
16 context.Visit(this);
17 context.Visit(this);
17 }
18 }
18 }
19 }
19 } No newline at end of file
20 }
@@ -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 : ContainerItemElement {
6 public class NamespaceElement : AbstractContainerItem {
7
7
8 [XmlAttribute("name")]
8 [XmlAttribute("name")]
9 public string Name { get; set; }
9 public string Name { get; set; }
10
10
11 public override void Visit(ContainerBuilder context) {
11 public override void Visit(ContainerBuilder context) {
12 context.Visit(this);
12 context.Visit(this);
13 }
13 }
14 }
14 }
15 } No newline at end of file
15 }
@@ -1,19 +1,20
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 : AbstractMemberInjection {
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 [XmlElement("array", typeof(ArrayParameterElement))]
13 public InjectionParameterElement Value { get; set; }
14 public InjectionParameterElement Value { get; set; }
14
15
15 internal override void Visit(TypeRegistrationBuilder context) {
16 internal override void Visit(TypeRegistrationBuilder context) {
16 context.Visit(this);
17 context.Visit(this);
17 }
18 }
18 }
19 }
19 } No newline at end of file
20 }
@@ -1,28 +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 : TypeAbstractRegistration {
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("mapTo")]
14 [XmlAttribute("mapTo")]
15 public string MapToType { get; set; }
15 public string MapToType { 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 AbstractMemberInjection[] Injectors { get; set; }
22
23 public override Type GetImplementationType(Func<string, Type> resolver) {
24 return string.IsNullOrEmpty(MapToType) ? null : resolver(MapToType);
25 }
22
26
23 public override void Visit(ContainerBuilder context) {
27 public override void Visit(TypeRegistrationBuilder builder) {
24 context.Visit(this);
28 if(Injectors != null)
29 foreach(var injector in Injectors)
30 injector.Visit(builder);
25 }
31 }
32
33
26 }
34 }
27
35
28 } No newline at end of file
36 }
@@ -1,21 +1,43
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.ComponentModel;
3 using System.ComponentModel;
4 using System.Linq;
4 using System.Linq;
5 using System.Xml.Serialization;
5 using System.Xml.Serialization;
6 using Implab.Xml;
6 using Implab.Xml;
7 using Unity.Injection;
7 using Unity.Injection;
8 using Unity.Lifetime;
8 using Unity.Registration;
9 using Unity.Registration;
9
10
10 namespace Implab.ServiceHost.Unity {
11 namespace Implab.ServiceHost.Unity {
12 /// <summary>
13 /// Базовый класс для формирования записей в контейнере, созволяет указать время жизни для записи
14 /// </summary>
11 public abstract class RegistrationBuilder {
15 public abstract class RegistrationBuilder {
12 public Type RegistrationType {
16 public Type RegistrationType {
13 get;
17 get;
14 private set;
18 private set;
15 }
19 }
16
20
21 internal LifetimeManager Lifetime { get; set; }
22
17 protected RegistrationBuilder(Type registrationType) {
23 protected RegistrationBuilder(Type registrationType) {
18 RegistrationType = registrationType;
24 RegistrationType = registrationType;
19 }
25 }
26
27 internal void Visit(SingletonLifetimeElement simgletonLifetime) {
28 Lifetime = new SingletonLifetimeManager();
29 }
30
31 internal void Visit(ContainerLifetimeElement containerLifetime) {
32 Lifetime = new ContainerControlledLifetimeManager();
33 }
34
35 internal void Visit(HierarchicalLifetimeElement hierarchicalLifetime) {
36 Lifetime = new HierarchicalLifetimeManager();
37 }
38
39 internal void Visist(ContextLifetimeElement contextLifetime) {
40 Lifetime = new PerResolveLifetimeManager();
41 }
20 }
42 }
21 } No newline at end of file
43 }
@@ -1,43 +1,29
1 using System;
1 using System;
2 using System.Xml;
2 using System.Xml;
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 SerializedElement : AbstractRegistration, ISerializedValue {
7 public class SerializedElement : InstanceAbstractRegistration {
8 [XmlAttribute("href")]
8 [XmlAttribute("href")]
9 public string Location { get; set; }
9 public string Location { get; set; }
10
10
11 [XmlAttribute("serializedType")]
11 [XmlAttribute("serializedType")]
12 public string SerializedType { get; set; }
12 public string SerializedType { get; set; }
13
13
14
14
15 [XmlAnyElement]
15 [XmlAnyElement]
16 public XmlElement[] Content { get; set; }
16 public XmlElement[] Content { get; set; }
17
17
18 string ISerializedValue.TypeName {
18 public override void Visit(InstanceRegistrationBuilder builder) {
19 get {
19 base.Visit(builder);
20 return string.IsNullOrEmpty(SerializedType) ? RegistrationType : SerializedType;
21 }
22 }
23
24 public string TypeName => throw new NotImplementedException();
25
26 public override void Visit(ContainerBuilder context) {
27 context.Visit(this);
28 }
29
20
30 public XmlReader GetReader() {
21 var parameter = new SerializedParameterElement {
31 if (!string.IsNullOrEmpty(Location))
22 TypeName = SerializedType,
32 return XmlReader.Create(Location);
23 Location = Location,
33 if (Content != null && Content.Length > 0)
24 Content = Content
34 return Content[0].CreateNavigator().ReadSubtree();
25 };
35
26 parameter.Visit(builder.ValueBuilder);
36 throw new Exception("No content found, expected XML document");
37 }
38
39 public void Visit(InjectionValueBuilder builder) {
40 throw new NotImplementedException();
41 }
27 }
42 }
28 }
43 } No newline at end of file
29 }
@@ -1,28 +1,33
1 using System;
1 using System;
2 using System.Xml;
2 using System.Xml;
3 using System.Xml.Schema;
3 using System.Xml.Schema;
4 using System.Xml.Serialization;
4 using System.Xml.Serialization;
5
5
6 namespace Implab.ServiceHost.Unity
6 namespace Implab.ServiceHost.Unity
7 {
7 {
8 public class SerializedParameterElement : InjectionParameterElement, ISerializedValue {
8 public class SerializedParameterElement : InjectionParameterElement {
9 [XmlAttribute("href")]
9 [XmlAttribute("href")]
10 public string Location { get; set; }
10 public string Location { get; set; }
11
11
12 [XmlAnyElement]
12 [XmlAnyElement]
13 public XmlElement[] Content { get; set; }
13 public XmlElement[] Content { get; set; }
14
14
15 public XmlReader GetReader() {
15 public XmlReader GetReader() {
16 if (!string.IsNullOrEmpty(Location))
16 if (!string.IsNullOrEmpty(Location))
17 return XmlReader.Create(Location);
17 return XmlReader.Create(Location);
18 if (Content != null && Content.Length > 0)
18 if (Content != null && Content.Length > 0)
19 return Content[0].CreateNavigator().ReadSubtree();
19 return Content[0].CreateNavigator().ReadSubtree();
20
20
21 throw new Exception("No content found, expected XML document");
21 throw new Exception("No content found, expected XML document");
22 }
22 }
23
23
24 public override void Visit(InjectionValueBuilder builder) {
24 public override void Visit(InjectionValueBuilder builder) {
25 builder.Visit(this);
25 var type = builder.ResolveInjectedValueType(TypeName);
26
27 var serializer = new XmlSerializer(type);
28 using(var reader = GetReader())
29 builder.SetValue(type, serializer.Deserialize(reader));
30
26 }
31 }
27 }
32 }
28 } No newline at end of file
33 }
@@ -1,10 +1,8
1 using Unity.Lifetime;
2
3 namespace Implab.ServiceHost.Unity
1 namespace Implab.ServiceHost.Unity
4 {
2 {
5 public class SimgletonLifetimeElement : LifetimeElement {
3 public class SingletonLifetimeElement : LifetimeElement {
6 public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
4 public override void Visit(RegistrationBuilder builder) {
7 return new SingletonLifetimeManager();
5 builder.Visit(this);
8 }
6 }
9 }
7 }
10 } No newline at end of file
8 }
@@ -1,161 +1,175
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 OpenArray,
21
22 CloseArray,
23
20 Eof
24 Eof
21 }
25 }
22
26
23 readonly Regex _tokens = new Regex(@"([\w\+]+)|\s*([\.{},])\s*");
27 readonly Regex _tokens = new Regex(@"([\w\+]+)|\s*([\.{},\[\]])\s*");
24
28
25 TokenType m_token;
29 TokenType m_token;
26
30
27 string m_tokenValue;
31 string m_tokenValue;
28
32
29 int m_pos;
33 int m_pos;
30
34
31 int m_tokenPos;
35 int m_tokenPos;
32
36
33 readonly string m_text;
37 readonly string m_text;
34
38
35 TokenType Token { get { return m_token; } }
39 TokenType Token { get { return m_token; } }
36
40
37 string TokenValue { get { return m_tokenValue; } }
41 string TokenValue { get { return m_tokenValue; } }
38
42
39 int TokenPos { get { return m_tokenPos; } }
43 int TokenPos { get { return m_tokenPos; } }
40
44
41 public TypeReferenceParser(string text) {
45 public TypeReferenceParser(string text) {
42 Safe.ArgumentNotEmpty(text, nameof(text));
46 Safe.ArgumentNotEmpty(text, nameof(text));
43 m_text = text;
47 m_text = text;
44 }
48 }
45
49
46 bool ReadToken() {
50 bool ReadToken() {
47 if (m_pos >= m_text.Length) {
51 if (m_pos >= m_text.Length) {
48 m_token = TokenType.Eof;
52 m_token = TokenType.Eof;
49 m_tokenValue = null;
53 m_tokenValue = null;
50 return false;
54 return false;
51 }
55 }
52
56
53 var m = _tokens.Match(m_text, m_pos);
57 var m = _tokens.Match(m_text, m_pos);
54
58
55 if (m.Success) {
59 if (m.Success) {
56 m_tokenPos = m_pos;
60 m_tokenPos = m_pos;
57 m_pos += m.Length;
61 m_pos += m.Length;
58 if (m.Groups[1].Success) {
62 if (m.Groups[1].Success) {
59 m_token = TokenType.Word;
63 m_token = TokenType.Word;
60 m_tokenValue = m.Groups[1].Value;
64 m_tokenValue = m.Groups[1].Value;
61 } else if (m.Groups[2].Success) {
65 } else if (m.Groups[2].Success) {
62 m_tokenValue = null;
66 m_tokenValue = null;
63 switch (m.Groups[2].Value) {
67 switch (m.Groups[2].Value) {
64 case "{":
68 case "{":
65 m_token = TokenType.OpenList;
69 m_token = TokenType.OpenList;
66 break;
70 break;
67 case "}":
71 case "}":
68 m_token = TokenType.CloseList;
72 m_token = TokenType.CloseList;
69 break;
73 break;
70 case ".":
74 case ".":
71 m_token = TokenType.Dot;
75 m_token = TokenType.Dot;
72 break;
76 break;
73 case ",":
77 case ",":
74 m_token = TokenType.Comma;
78 m_token = TokenType.Comma;
75 break;
79 break;
80 case "[":
81 m_token = TokenType.OpenArray;
82 break;
83 case "]":
84 m_token = TokenType.CloseArray;
85 break;
76 }
86 }
77 }
87 }
78 return true;
88 return true;
79 }
89 }
80 throw new FormatException($"Failed to parse '{m_text}' at pos {m_pos}");
90 throw new FormatException($"Failed to parse '{m_text}' at pos {m_pos}");
81 }
91 }
82
92
83 public TypeReference Parse() {
93 public TypeReference Parse() {
84 var result = ReadTypeReference();
94 var result = ReadTypeReference();
85 if (ReadToken())
95 if (Token != TokenType.Eof)
86 ThrowUnexpectedToken();
96 ThrowUnexpectedToken();
87 return result;
97 return result;
88 }
98 }
89
99
90 string[] ReadTypeName() {
100 string[] ReadTypeName() {
91 var parts = new List<string>();
101 var parts = new List<string>();
92
102
93 string current = null;
103 string current = null;
94 bool stop = false;
104 bool stop = false;
95 while ((!stop) && ReadToken()) {
105 while ((!stop) && ReadToken()) {
96 switch (Token) {
106 switch (Token) {
97 case TokenType.Word:
107 case TokenType.Word:
98 if (current != null)
108 if (current != null)
99 ThrowUnexpectedToken();
109 ThrowUnexpectedToken();
100 current = TokenValue;
110 current = TokenValue;
101 break;
111 break;
102 case TokenType.Dot:
112 case TokenType.Dot:
103 if (current == null)
113 if (current == null)
104 ThrowUnexpectedToken();
114 ThrowUnexpectedToken();
105 parts.Add(current);
115 parts.Add(current);
106 current = null;
116 current = null;
107 break;
117 break;
108 default:
118 default:
109 stop = true;
119 stop = true;
110 break;
120 break;
111 }
121 }
112 }
122 }
113 if (current != null)
123 if (current != null)
114 parts.Add(current);
124 parts.Add(current);
115
125
116 if (parts.Count == 0)
126 if (parts.Count == 0)
117 return null;
127 return null;
118
128
119 return parts.ToArray();
129 return parts.ToArray();
120 }
130 }
121
131
122 TypeReference ReadTypeReference() {
132 TypeReference ReadTypeReference() {
123
133
124 var parts = ReadTypeName();
134 var parts = ReadTypeName();
125 if (parts == null)
135 if (parts == null)
126 return null;
136 return null;
127
137
128 var typeReference = new TypeReference {
138 var typeReference = new TypeReference {
129 Namespace = string.Join(".", parts, 0, parts.Length - 1),
139 Namespace = string.Join(".", parts, 0, parts.Length - 1),
130 TypeName = parts[parts.Length - 1]
140 TypeName = parts[parts.Length - 1]
131 };
141 };
132
142
133 switch (Token) {
143 switch (Token) {
134 case TokenType.OpenList:
144 case TokenType.OpenList:
135 typeReference.GenericParameters = ReadTypeReferenceList();
145 typeReference.GenericParameters = ReadTypeReferenceList();
136 if (Token != TokenType.CloseList)
146 if (Token != TokenType.CloseList)
137 ThrowUnexpectedToken();
147 ThrowUnexpectedToken();
138 ReadToken();
148 ReadToken();
139 break;
149 break;
140 }
150 }
141
151
142 return typeReference;
152 return typeReference;
143 }
153 }
144
154
155 int CountDimentions() {
156 return 0;
157 }
158
145 TypeReference[] ReadTypeReferenceList() {
159 TypeReference[] ReadTypeReferenceList() {
146 var list = new List<TypeReference>();
160 var list = new List<TypeReference>();
147
161
148 do {
162 do {
149 var typeReference = ReadTypeReference();
163 var typeReference = ReadTypeReference();
150 list.Add(typeReference);
164 list.Add(typeReference);
151 } while (Token == TokenType.Comma);
165 } while (Token == TokenType.Comma);
152
166
153 return list.ToArray();
167 return list.ToArray();
154 }
168 }
155
169
156 void ThrowUnexpectedToken() {
170 void ThrowUnexpectedToken() {
157 throw new FormatException($"Unexpected '{Token}' at pos {TokenPos}: -->{m_text.Substring(TokenPos, Math.Min(m_text.Length - TokenPos, 10))}");
171 throw new FormatException($"Unexpected '{Token}' at pos {TokenPos}: -->{m_text.Substring(TokenPos, Math.Min(m_text.Length - TokenPos, 10))}");
158 }
172 }
159
173
160 }
174 }
161 } No newline at end of file
175 }
@@ -1,77 +1,77
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 Unity.Injection;
4 using Unity.Injection;
5 using Unity.Registration;
5 using Unity.Registration;
6
6
7 namespace Implab.ServiceHost.Unity {
7 namespace Implab.ServiceHost.Unity {
8 public class TypeRegistrationBuilder : RegistrationBuilder {
8 public class TypeRegistrationBuilder : RegistrationBuilder {
9
9
10 readonly TypeResolver m_resolver;
10 readonly TypeResolver m_resolver;
11
11
12 readonly List<InjectionMember> m_injections = new List<InjectionMember>();
12 readonly List<InjectionMember> m_injections = new List<InjectionMember>();
13
13
14 public InjectionMember[] Injections { get { return m_injections.ToArray(); } }
14 internal InjectionMember[] Injections { get { return m_injections.ToArray(); } }
15
15
16 public Type ImplementationType {
16 public Type ImplementationType {
17 get;
17 get;
18 private set;
18 private set;
19 }
19 }
20
20
21 internal TypeRegistrationBuilder(TypeResolver resolver, Type registrationType, Type implementationType) : base(registrationType) {
21 internal TypeRegistrationBuilder(TypeResolver resolver, Type registrationType, Type implementationType) : base(registrationType) {
22 ImplementationType = implementationType;
22 ImplementationType = implementationType;
23
23
24 // when registering a generic mapping, register all generic parameter names as local types
24 // when registering a generic mapping, register all generic parameter names as local types
25 if (ImplementationType.IsGenericTypeDefinition) {
25 if (ImplementationType.IsGenericTypeDefinition) {
26 m_resolver = new TypeResolver(resolver);
26 m_resolver = new TypeResolver(resolver);
27
27
28 foreach (var p in ImplementationType.GetGenericArguments())
28 foreach (var p in ImplementationType.GetGenericArguments())
29 m_resolver.AddMapping(p.Name, p);
29 m_resolver.AddMapping(p.Name, p);
30 } else {
30 } else {
31 m_resolver = resolver;
31 m_resolver = resolver;
32 }
32 }
33 }
33 }
34
34
35 internal void Visit(ConstructorInjectionElement constructorInjection) {
35 internal void Visit(ConstructorInjectionElement constructorInjection) {
36
36
37
37
38 var parameters = constructorInjection.Parameters?
38 var parameters = constructorInjection.Parameters?
39 .Select(x => {
39 .Select(x => {
40 var valueBuilder = new InjectionValueBuilder(m_resolver, null);
40 var valueBuilder = new InjectionValueBuilder(m_resolver, null);
41 x.Visit(valueBuilder);
41 x.Visit(valueBuilder);
42 return valueBuilder.Injection;
42 return valueBuilder.Injection;
43 })
43 })
44 .ToArray();
44 .ToArray();
45
45
46 var injection = parameters != null ? new InjectionConstructor(parameters) : new InjectionConstructor();
46 var injection = parameters != null ? new InjectionConstructor(parameters) : new InjectionConstructor();
47 m_injections.Add(injection);
47 m_injections.Add(injection);
48 }
48 }
49
49
50 internal void Visit(MethodInjectionElement methodInjection) {
50 internal void Visit(MethodInjectionElement methodInjection) {
51 var valueContext = new InjectionValueBuilder(m_resolver, null);
51 var valueContext = new InjectionValueBuilder(m_resolver, null);
52
52
53 var parameters = methodInjection.Parameters?
53 var parameters = methodInjection.Parameters?
54 .Select(x => {
54 .Select(x => {
55 var valueBuilder = new InjectionValueBuilder(m_resolver, null);
55 var valueBuilder = new InjectionValueBuilder(m_resolver, null);
56 x.Visit(valueBuilder);
56 x.Visit(valueBuilder);
57 return valueBuilder.Injection;
57 return valueBuilder.Injection;
58 })
58 })
59 .ToArray();
59 .ToArray();
60
60
61 var injection = parameters != null ? new InjectionMethod(methodInjection.Name, parameters) : new InjectionMethod(methodInjection.Name);
61 var injection = parameters != null ? new InjectionMethod(methodInjection.Name, parameters) : new InjectionMethod(methodInjection.Name);
62 m_injections.Add(injection);
62 m_injections.Add(injection);
63 }
63 }
64
64
65 internal void Visit(PropertyInjectionElement propertyInjection) {
65 internal void Visit(PropertyInjectionElement propertyInjection) {
66 if (propertyInjection.Value == null)
66 if (propertyInjection.Value == null)
67 throw new Exception($"A value value must be specified for the property '{propertyInjection.Name}'");
67 throw new Exception($"A value value must be specified for the property '{propertyInjection.Name}'");
68
68
69 var propertyType = RegistrationType.GetProperty(propertyInjection.Name)?.PropertyType;
69 var propertyType = RegistrationType.GetProperty(propertyInjection.Name)?.PropertyType;
70 var valueContext = new InjectionValueBuilder(m_resolver, propertyType);
70 var valueContext = new InjectionValueBuilder(m_resolver, propertyType);
71
71
72 propertyInjection.Value.Visit(valueContext);
72 propertyInjection.Value.Visit(valueContext);
73 var injection = new InjectionProperty(propertyInjection.Name, valueContext.Injection);
73 var injection = new InjectionProperty(propertyInjection.Name, valueContext.Injection);
74 m_injections.Add(injection);
74 m_injections.Add(injection);
75 }
75 }
76 }
76 }
77 } No newline at end of file
77 }
@@ -1,129 +1,125
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 {
10 using static Trace<TypeResolver>;
9 using static Trace<TypeResolver>;
11 public class TypeResolver
10 public class TypeResolver {
12 {
13 readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>();
11 readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>();
14
12
15 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
13 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
16 readonly LinkedList<string> m_namespases = new LinkedList<string>();
14 readonly LinkedList<string> m_namespases = new LinkedList<string>();
17
15
18 LinkedListNode<string> m_insertAt;
16 LinkedListNode<string> m_insertAt;
19
17
20 readonly TypeResolver m_parent;
18 readonly TypeResolver m_parent;
21
19
22 public TypeResolver() : this(null) {
20 public TypeResolver() : this(null) {
23
21
24 }
22 }
25
23
26 public TypeResolver(TypeResolver parent) {
24 public TypeResolver(TypeResolver parent) {
27 m_parent = parent;
25 m_parent = parent;
28 m_insertAt = new LinkedListNode<string>(string.Empty);
26 m_insertAt = new LinkedListNode<string>(string.Empty);
29 m_namespases.AddFirst(m_insertAt);
27 m_namespases.AddFirst(m_insertAt);
30 }
28 }
31
29
32 public void AddNamespace(string ns) {
30 public void AddNamespace(string ns) {
33 Safe.ArgumentMatch(ns, nameof(ns), _nsRx);
31 Safe.ArgumentMatch(ns, nameof(ns), _nsRx);
34 if (m_insertAt != null)
32 if (m_insertAt != null)
35 m_namespases.AddAfter(m_insertAt, ns);
33 m_namespases.AddAfter(m_insertAt, ns);
36 else
34 else
37 m_namespases.AddFirst(ns);
35 m_namespases.AddFirst(ns);
38 }
36 }
39
37
40 public void AddMapping(string typeName, Type type) {
38 public void AddMapping(string typeName, Type type) {
41 Safe.ArgumentNotEmpty(typeName, nameof(typeName));
39 Safe.ArgumentNotEmpty(typeName, nameof(typeName));
42 Safe.ArgumentNotNull(type, nameof(type));
40 Safe.ArgumentNotNull(type, nameof(type));
43
41
44 m_cache[typeName] = type;
42 m_cache[typeName] = type;
45 }
43 }
46
44
47 public Type Resolve(TypeReference reference) {
45 public Type Resolve(TypeReference reference) {
48 var args = reference.IsGeneric && !reference.IsOpenGeneric ? reference.GenericParameters?.Select(Resolve).ToArray() : null;
46 var args = reference.IsGeneric && !reference.IsOpenGeneric ? reference.GenericParameters?.Select(Resolve).ToArray() : null;
49 var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0;
47 var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0;
50
48
51 Type resolved;
49 Type resolved;
52 if(!m_cache.TryGetValue(reference.ToString(), out resolved)) {
50 if (!m_cache.TryGetValue(reference.ToString(), out resolved)) {
53 resolved = ResolveInternal(reference, args, argc);
51 resolved = ResolveInternal(reference, args, argc);
54 if (resolved == null)
52 if (resolved == null)
55 throw new Exception($"Failed to resolve {reference}");
53 throw new Exception($"Failed to resolve {reference}");
56 m_cache[reference.ToString()] = resolved;
54 m_cache[reference.ToString()] = resolved;
57 }
55 }
58
56
59 return resolved;
57 return resolved;
60 }
58 }
61
59
62 public Type Resolve(string typeSpec) {
60 public Type Resolve(string typeSpec) {
63 return Resolve(TypeReference.Parse(typeSpec));
61 return Resolve(TypeReference.Parse(typeSpec));
64 }
62 }
65
63
66 Type ResolveInternal(TypeReference reference, Type[] args, int argc) {
64 Type ResolveInternal(TypeReference reference, Type[] args, int argc) {
67 var resolved = ProbeInNamespaces(
65 var resolved = ProbeInNamespaces(
68 String.Join(".", new [] { reference.Namespace, reference.TypeName }.Where(x => !string.IsNullOrEmpty(x)) ),
66 String.Join(".", new[] { reference.Namespace, reference.TypeName }.Where(x => !string.IsNullOrEmpty(x))),
69 args,
67 args,
70 argc,
68 argc,
71 reference.IsArray,
69 reference.IsArray,
72 reference.ToString()
70 reference.ToString()
73 );
71 );
74
72
75 if (resolved == null && m_parent != null)
73 if (resolved == null && m_parent != null)
76 resolved = m_parent.Resolve(reference);
74 resolved = m_parent.ResolveInternal(reference, args, argc);
77
75
78 return resolved;
76 return resolved;
79 }
77 }
80
78
81 public Type ProbeInNamespaces(string localName, Type[] args, int argc, bool isArray, string referenceName) {
79 public Type ProbeInNamespaces(string localName, Type[] args, int argc, bool isArray, string referenceName) {
82 foreach (var ns in m_namespases) {
80 foreach (var ns in m_namespases) {
83 var typeName = FormatName(new [] { ns, localName}, argc, args, isArray);
81 var typeName = FormatName(new[] { ns, localName }, argc);
84
82
85 var resolved = Probe(typeName);
83 var resolved = Probe(typeName);
86 if (resolved != null) {
84 if (resolved != null) {
85 if (args != null && args.Length > 0) {
86 resolved = resolved.MakeGenericType(args);
87 }
88
89 if (isArray)
90 resolved = resolved.MakeArrayType();
91
87 Log("Probe succeed {0} in '{1}': {2} -> {3}", referenceName, ns, typeName, resolved.AssemblyQualifiedName);
92 Log("Probe succeed {0} in '{1}': {2} -> {3}", referenceName, ns, typeName, resolved.AssemblyQualifiedName);
88 return resolved;
93 return resolved;
89 } else {
94 } else {
90 Log("Probe failed {0} in '{1}': {2}", referenceName, ns, typeName);
95 Log("Probe failed {0} in '{1}': {2}", referenceName, ns, typeName);
91 }
96 }
92 }
97 }
93
98
94 return null;
99 return null;
95 }
100 }
96
101
97 Type Probe(string typeName) {
102 Type Probe(string typeName) {
98 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
103 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
99
104
100 foreach(var assembly in assemblies) {
105 foreach (var assembly in assemblies) {
101 var type = assembly.GetType(typeName);
106 var type = assembly.GetType(typeName);
102 if (type != null)
107 if (type != null)
103 return type;
108 return type;
104 }
109 }
105 return null;
110 return null;
106 }
111 }
107
112
108 string FormatName(string[] parts, int argc, Type[] args, bool isArray) {
113 string FormatName(string[] parts, int argc) {
109 var builder = new StringBuilder();
114 var builder = new StringBuilder();
110
115
111 builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x))));
116 builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x))));
112 if (argc > 0) {
117 if (argc > 0) {
113 builder.Append('`');
118 builder.Append('`');
114 builder.Append(argc);
119 builder.Append(argc);
115 }
120 }
116
121
117 if (args!= null && args.Length > 0) {
122 return builder.ToString();
118 builder.Append('[');
119 builder.Append(string.Join(",", args.Select(x => $"[{x.AssemblyQualifiedName}]")));
120 builder.Append(']');
121 }
122
123 if(isArray)
124 builder.Append("[]");
125
126 return builder.ToString();
127 }
123 }
128 }
124 }
129 } No newline at end of file
125 }
@@ -1,28 +1,31
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 ValueElement : AbstractRegistration, ITextValue {
4 public class ValueElement : InstanceAbstractRegistration {
5
5
6 [XmlAttribute("value")]
6 [XmlAttribute("value")]
7 public string Value { get; set; }
7 public string Value { get; set; }
8
8
9 [XmlText]
9 [XmlText]
10 public string Text { get; set; }
10 public string Text { get; set; }
11
11
12 string ITextValue.Value {
12 string GetTextValue() {
13 get {
13 return string.IsNullOrEmpty(Value) ? Text : Value;
14 return string.IsNullOrEmpty(Value) ? Text : Value;
15 }
16 }
14 }
17
15
18 public string TypeName {
16 public string TypeName {
19 get {
17 get {
20 return RegistrationType;
18 return RegistrationType;
21 }
19 }
22 }
20 }
23
21
24 public override void Visit(ContainerBuilder context) {
22 public override void Visit(InstanceRegistrationBuilder builder) {
25 context.Visit(this);
23 base.Visit(builder);
24 var parameter = new ValueParameterElement {
25 Value = Value,
26 Text = Text
27 };
28 parameter.Visit(builder.ValueBuilder);
26 }
29 }
27 }
30 }
28 } No newline at end of file
31 }
@@ -1,13 +1,21
1 using System.ComponentModel;
1 using System.Xml.Serialization;
2 using System.Xml.Serialization;
2
3
3 namespace Implab.ServiceHost.Unity {
4 namespace Implab.ServiceHost.Unity {
4 public class ValueParameterElement : InjectionParameterElement, ITextValue {
5 public class ValueParameterElement : InjectionParameterElement {
5 [XmlText]
6 [XmlAttribute("value")]
6 [XmlAttribute("value")]
7 public string Value { get; set; }
7 public string Value { get; set; }
8
8
9 [XmlText]
10 public string Text { get; set; }
11
12 string GetTextValue() {
13 return string.IsNullOrEmpty(Value) ? Text : Value;
14 }
15
9 public override void Visit(InjectionValueBuilder builder) {
16 public override void Visit(InjectionValueBuilder builder) {
10 builder.Visit(this);
17 var type = builder.ResolveInjectedValueType(TypeName);
18 builder.SetValue(type, TypeDescriptor.GetConverter(type).ConvertFromString(GetTextValue()));
11 }
19 }
12 }
20 }
13 } No newline at end of file
21 }
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/readme.md to Implab.ServiceHost/docs/XmlConfiguration.md
NO CONTENT: file renamed from Implab.ServiceHost/Unity/readme.md to Implab.ServiceHost/docs/XmlConfiguration.md
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
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