##// END OF EJS Templates
Container configuration cleanup, RC2
cin -
r279:8714471e8d78 v3
parent child
Show More
@@ -0,0 +1,40
1 using System.IO;
2 using Unity;
3
4 namespace Implab.ServiceHost.Unity
5 {
6 public static class UnityContainerExtensions
7 {
8 public static IUnityContainer LoadXmlConfiguration(this IUnityContainer container, string file, ContainerConfigurationSchema schema) {
9 Safe.ArgumentNotNull(container, nameof(container));
10 var builder = new ContainerBuilder(container,schema);
11 builder.LoadConfig(file);
12 return builder.Container;
13 }
14
15 public static IUnityContainer LoadXmlConfiguration(this IUnityContainer container, Stream stream, ContainerConfigurationSchema schema) {
16 Safe.ArgumentNotNull(container, nameof(container));
17 Safe.ArgumentNotNull(stream, nameof(stream));
18
19 if (schema == null)
20 schema = ContainerConfigurationSchema.Default;
21
22 var builder = new ContainerBuilder(container,schema);
23 var config = (ContainerElement)schema.Serializer.Deserialize(stream);
24 if (config.Items != null) {
25 foreach(var item in config.Items)
26 item?.Visit(builder);
27 }
28
29 return builder.Container;
30 }
31
32 public static IUnityContainer LoadXmlConfiguration(this IUnityContainer container, Stream stream) {
33 return LoadXmlConfiguration(container, stream, ContainerConfigurationSchema.Default);
34 }
35
36 public static IUnityContainer LoadXmlConfiguration(this IUnityContainer container, string file) {
37 return LoadXmlConfiguration(container, file, ContainerConfigurationSchema.Default);
38 }
39 }
40 } No newline at end of file
@@ -1,136 +1,141
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Diagnostics;
3 using System.Diagnostics;
4 using System.Linq;
4 using System.Linq;
5 using Implab.Components;
5 using Implab.Components;
6 using Implab.Diagnostics;
6 using Implab.Diagnostics;
7 using Implab.ServiceHost.Unity;
7 using Implab.ServiceHost.Unity;
8 using Implab.Xml;
8 using Implab.Xml;
9 using Unity;
9 using Unity;
10 using Unity.Injection;
10 using Unity.Injection;
11 using Unity.Registration;
11 using Unity.Registration;
12
12
13 namespace Implab.Playground {
13 namespace Implab.Playground {
14
14
15 public class Foo {
15 public class Foo {
16
16
17 public class Bar {
17 public class Bar {
18
18
19 }
19 }
20
20
21 public string Name { get; set; }
21 public string Name { get; set; }
22
22
23 public int IntValue { get; set; }
23 public int IntValue { get; set; }
24
24
25 public string StringValue { get; set; }
25 public string StringValue { get; set; }
26
26
27 public void AddRange(Foo[] items) {
27 public void AddRange(Foo[] items) {
28 Console.WriteLine($"AddRange: Foo[]");
28 Console.WriteLine($"AddRange: Foo[]");
29 }
29 }
30
30
31 }
31 }
32
32
33 public class FooFactory : IFactory<Foo>, IFactory<Foo.Bar> {
33 public class FooFactory : IFactory<Foo>, IFactory<Foo.Bar> {
34
34
35 public bool UseSsl { get; set; }
35 public bool UseSsl { get; set; }
36
36
37 public string Connection { get; set; }
37 public string Connection { get; set; }
38
38
39 public Foo Create() {
39 public Foo Create() {
40 return new Foo() {
40 return new Foo() {
41 Name = "AutoFac"
41 Name = "AutoFac"
42 };
42 };
43 }
43 }
44
44
45 Foo.Bar IFactory<Foo.Bar>.Create() {
45 Foo.Bar IFactory<Foo.Bar>.Create() {
46 return new Foo.Bar();
46 return new Foo.Bar();
47 }
47 }
48 }
48 }
49
49
50 public interface IContainer<T> {
50 public interface IContainer<T> {
51 T Instance { get; set; }
51 T Instance { get; set; }
52 }
52 }
53
53
54 public class Container<T> : IContainer<T> {
54 public class Container<T> : IContainer<T> {
55 public class Bar {
55 public class Bar {
56
56
57 }
57 }
58
58
59 public class Bar<T2> {
59 public class Bar<T2> {
60 public class Baz {
60 public class Baz {
61
61
62 }
62 }
63
63
64 }
64 }
65
65
66 public Container() {
66 public Container() {
67
67
68 }
68 }
69
69
70 public Container(T instance) {
70 public Container(T instance) {
71 Instance = instance;
71 Instance = instance;
72 }
72 }
73
73
74 public T Instance { get; set; }
74 public T Instance { get; set; }
75
75
76 public void SetInstance(T value) {
76 public void SetInstance(T value) {
77 Instance = value;
77 Instance = value;
78 }
78 }
79
79
80 public void AddRange(List<T> items) {
80 public void AddRange(List<T> items) {
81 Console.WriteLine($"AddRange: {typeof(List<T>)}");
81 Console.WriteLine($"AddRange: {typeof(List<T>)}");
82 }
82 }
83
83
84 public void AddRange(T[] items) {
84 public void AddRange(T[] items) {
85 Console.WriteLine($"AddRange: T[] ofType {typeof(T[])}");
85 Console.WriteLine($"AddRange: T[] ofType {typeof(T[])}");
86 }
86 }
87 }
87 }
88
88
89 public class Program {
89 public class Program {
90
90
91 static void Main(string[] args) {
91 static void Main(string[] args) {
92 var listener = new SimpleTraceListener(Console.Out);
92 var listener = new SimpleTraceListener(Console.Out);
93 var source = Trace<TypeResolver>.TraceSource;
93 var source = Trace<TypeResolver>.TraceSource;
94 source.Switch.Level = SourceLevels.All;
94 source.Switch.Level = SourceLevels.All;
95 source.Listeners.Add(listener);
95 source.Listeners.Add(listener);
96
96
97 var resolver = new TypeResolver();
97 var stopwatch = new Stopwatch();
98 resolver.AddNamespace("System");
98 stopwatch.Start();
99 resolver.AddNamespace("System.Collections.Generic");
99
100 resolver.AddNamespace("Implab.Playground");
100 var container = new UnityContainer();
101 resolver.AddMapping("string", typeof(string));
101
102 resolver.AddMapping("listOf`1", typeof(List<>));
102 Console.WriteLine($"Created: {stopwatch.ElapsedMilliseconds}");
103 stopwatch.Restart();
104
105 container.LoadXmlConfiguration("data/sample.xml");
103
106
104 var spec = TypeReference.Parse("Container{listOf{string}}+Bar{List{string}}");
107 Console.WriteLine($"Loaded: {stopwatch.ElapsedMilliseconds}");
105
108
106 var t = resolver.Resolve(spec, true);
109 stopwatch.Restart();
110 var instace1 = container.Resolve<IContainer<string>>();
111 Console.WriteLine($"Resolved1: {stopwatch.ElapsedMilliseconds}");
107
112
108 Console.WriteLine("{0}", t);
113 stopwatch.Restart();
109 Console.WriteLine("Spec: {0}", spec);
114 var instace2 = container.Resolve<IContainer<Foo>>();
110 Console.WriteLine("IsGenericType: {0}", t.IsGenericType);
115 Console.WriteLine($"Resolved2: {stopwatch.ElapsedMilliseconds}");
111 Console.WriteLine("IsGenericTypeDefinition: {0}", t.IsGenericTypeDefinition);
116
112 Console.WriteLine("ContainsGenericParameters: {0}", t.ContainsGenericParameters);
117 DisplayContainerRegistrations(container);
113 }
118 }
114
119
115 static void DisplayContainerRegistrations(IUnityContainer theContainer) {
120 static void DisplayContainerRegistrations(IUnityContainer theContainer) {
116 string regName, regType, mapTo, lifetime;
121 string regName, regType, mapTo, lifetime;
117 Console.WriteLine("Container has {0} Registrations:",
122 Console.WriteLine("Container has {0} Registrations:",
118 theContainer.Registrations.Count());
123 theContainer.Registrations.Count());
119 foreach (ContainerRegistration item in theContainer.Registrations) {
124 foreach (ContainerRegistration item in theContainer.Registrations) {
120 regType = item.RegisteredType.FullName;
125 regType = item.RegisteredType.FullName;
121 mapTo = item.MappedToType.FullName;
126 mapTo = item.MappedToType.FullName;
122 regName = item.Name ?? "[default]";
127 regName = item.Name ?? "[default]";
123 lifetime = item.LifetimeManager.LifetimeType.Name;
128 lifetime = item.LifetimeManager.LifetimeType.Name;
124 if (mapTo != regType) {
129 if (mapTo != regType) {
125 mapTo = " -> " + mapTo;
130 mapTo = " -> " + mapTo;
126 } else {
131 } else {
127 mapTo = string.Empty;
132 mapTo = string.Empty;
128 }
133 }
129 lifetime = lifetime.Substring(0, lifetime.Length - "LifetimeManager".Length);
134 lifetime = lifetime.Substring(0, lifetime.Length - "LifetimeManager".Length);
130 Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo, regName, lifetime);
135 Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo, regName, lifetime);
131 }
136 }
132 }
137 }
133
138
134
139
135 }
140 }
136 }
141 }
@@ -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 AbstractMemberInjection {
7 public abstract class AbstractMemberInjection : ITypeMemberInjection {
8 internal abstract void Visit(TypeRegistrationBuilder context);
8 public abstract void Visit(TypeRegistrationBuilder builder);
9 }
9 }
10 } No newline at end of file
10 }
@@ -1,42 +1,48
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 /// <summary>
8 /// <summary>
9 /// Базовая информаци о регистрации в контейнере: тип, имя и время жизни
9 /// Базовая информаци о регистрации в контейнере: тип, имя и время жизни
10 /// </summary>
10 /// </summary>
11 public abstract class AbstractRegistration : AbstractContainerItem {
11 public abstract class AbstractRegistration : AbstractContainerItem, IRegistration {
12
12
13 /// <summary>
13 /// <summary>
14 /// An optional name for a registration in the container
14 /// An optional name for a registration in the container
15 /// </summary>
15 /// </summary>
16 [XmlAttribute("name")]
16 [XmlAttribute("name")]
17 public string Name {
17 public string Name {
18 get; set;
18 get; set;
19 }
19 }
20
20
21 [XmlElement("signleton", typeof(SingletonLifetimeElement))]
21 [XmlElement("signleton", typeof(SingletonLifetimeElement))]
22 [XmlElement("context", typeof(ContextLifetimeElement))]
22 [XmlElement("context", typeof(ContextLifetimeElement))]
23 [XmlElement("container", typeof(ContainerLifetimeElement))]
23 [XmlElement("container", typeof(ContainerLifetimeElement))]
24 [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
24 [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
25 public LifetimeElement Lifetime {get; set;}
25 public LifetimeElement Lifetime {get; set;}
26
26
27 /// <summary>
27 /// <summary>
28 /// A type specification for the service registration,
28 /// A type specification for the service registration,
29 /// </summary>
29 /// </summary>
30 [XmlAttribute("type")]
30 [XmlAttribute("type")]
31 public string RegistrationType { get; set; }
31 public string RegistrationType { get; set; }
32
32
33 public virtual LifetimeManager GetLifetime(ContainerBuilder builder) {
34 return Lifetime?.GetLifetime(builder);
35 }
36
33 public virtual Type GetRegistrationType(Func<string,Type> resolver) {
37 public virtual Type GetRegistrationType(Func<string,Type> resolver) {
34 return resolver(RegistrationType);
38 return resolver(RegistrationType);
35 }
39 }
36
40
37 public virtual void Visit(RegistrationBuilder builder) {
41 public virtual Type GetRegistrationType(ContainerBuilder builder) {
38 Lifetime?.Visit(builder);
42 return builder.ResolveType(RegistrationType);
39 }
43 }
40
44
45
46
41 }
47 }
42 } No newline at end of file
48 }
@@ -1,17 +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 : AbstractMemberInjection {
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 [XmlElement("array", typeof(ArrayParameterElement))]
11 public InjectionParameterElement[] Parameters { get; set; }
11 public InjectionParameterElement[] Parameters { get; set; }
12
12
13 internal override void Visit(TypeRegistrationBuilder context) {
13 public override void Visit(TypeRegistrationBuilder builder) {
14 context.Visit(this);
14 builder.Visit(this);
15 }
15 }
16 }
16 }
17 } No newline at end of file
17 }
@@ -1,177 +1,111
1 using System;
1 using System;
2 using System.Reflection;
2 using System.Reflection;
3 using Unity;
3 using Unity;
4
4
5 namespace Implab.ServiceHost.Unity {
5 namespace Implab.ServiceHost.Unity {
6 public class ContainerBuilder {
6 public class ContainerBuilder {
7
7
8 readonly TypeResolver m_resolver;
8 readonly TypeResolver m_resolver;
9
9
10 readonly UnityContainer m_container;
10 readonly IUnityContainer m_container;
11
11
12 readonly ContainerConfigurationSchema m_schema;
12 readonly ContainerConfigurationSchema m_schema;
13
13
14 public UnityContainer Container {
14 public IUnityContainer Container {
15 get {
15 get {
16 return m_container;
16 return m_container;
17 }
17 }
18 }
18 }
19
19
20 public ContainerBuilder() : this(null, null) {
20 public ContainerBuilder() : this(null, null) {
21 }
21 }
22
22
23 public ContainerBuilder(UnityContainer container, ContainerConfigurationSchema schema) {
23 public ContainerBuilder(IUnityContainer container, ContainerConfigurationSchema schema) {
24 m_container = container ?? new UnityContainer();
24 m_container = container ?? new UnityContainer();
25 m_resolver = new TypeResolver();
25 m_resolver = new TypeResolver();
26 m_schema = schema ?? ContainerConfigurationSchema.Default;
26 m_schema = schema ?? ContainerConfigurationSchema.Default;
27 }
27 }
28
28
29 public Type ResolveType(string typeReference) {
29 public Type ResolveType(string typeReference) {
30 return m_resolver.Resolve(typeReference, true);
30 return string.IsNullOrEmpty(typeReference) ? null : m_resolver.Resolve(typeReference, true);
31 }
32
33
34 internal void Visit(TypeAbstractRegistration typeRegistration) {
35 var registrationType = typeRegistration.GetRegistrationType(ResolveType);
36 var implementationType = typeRegistration.GetImplementationType(ResolveType) ?? registrationType;
37
38 var registrationContext = new TypeRegistrationBuilder(
39 m_resolver,
40 registrationType,
41 implementationType
42 );
43
44 typeRegistration.Visit(registrationContext);
45
46 m_container.RegisterType(
47 registrationContext.RegistrationType,
48 registrationContext.ImplementationType,
49 typeRegistration.Name,
50 registrationContext.Lifetime,
51 registrationContext.Injections
52 );
53 }
54
55 internal void Visit(InstanceAbstractRegistration instanceRegistration) {
56 var registrationType = instanceRegistration.GetRegistrationType(ResolveType);
57
58 var builder = new InstanceRegistrationBuilder(m_resolver, registrationType);
59
60 instanceRegistration.Visit(builder);
61
62 m_container.RegisterInstance(
63 builder.ValueBuilder.ValueType,
64 instanceRegistration.Name,
65 builder.ValueBuilder.Value,
66 builder.Lifetime
67 );
68 }
69
70 internal void Visit(FactoryAbstractRegistratrion factoryRgistration) {
71 var registrationType = factoryRgistration.GetRegistrationType(ResolveType);
72
73 var builder = new FactoryRegistrationBuilder(registrationType);
74
75 factoryRgistration.Visit(builder);
76
77 m_container.RegisterType(
78 builder.RegistrationType,
79 factoryRgistration.Name,
80 builder.Lifetime,
81 builder.Factory
82 );
83 }
31 }
84
32
85 public void Visit(ITypeRegistration registration) {
33 public void Visit(ITypeRegistration registration) {
86 Safe.ArgumentNotNull(registration, nameof(registration));
34 Safe.ArgumentNotNull(registration, nameof(registration));
87
35
88 var registrationType = registration.GetRegistrationType(this);
36 var registrationType = registration.GetRegistrationType(this);
89 var implementationType = registration.GetImplementationType(this) ?? registrationType;
37 var implementationType = registration.GetImplementationType(this) ?? registrationType;
90
38
91 if (registrationType == null)
39 if (registrationType == null)
92 throw new Exception($"A type must be specified for the registration {registration.Name}");
40 throw new Exception($"A type must be specified for the registration {registration.Name}");
93
41
94 var builder = new TypeRegistrationBuilder(
42 var builder = new TypeRegistrationBuilder(
95 m_resolver,
43 m_resolver,
96 registrationType,
44 registrationType,
97 implementationType
45 implementationType
98 );
46 );
99
47
100 builder.Lifetime = registration.GetLifetime(this);
48 builder.Lifetime = registration.GetLifetime(this);
101
49
102 if (registration.MemberInjections != null) {
50 if (registration.MemberInjections != null) {
103 foreach(var member in registration.MemberInjections)
51 foreach(var member in registration.MemberInjections)
104 member.Visit(builder);
52 member.Visit(builder);
105 }
53 }
106
54
107 m_container.RegisterType(
55 m_container.RegisterType(
108 builder.RegistrationType,
56 builder.RegistrationType,
109 builder.ImplementationType,
57 builder.ImplementationType,
110 registration.Name,
58 registration.Name,
111 builder.Lifetime,
59 builder.Lifetime,
112 builder.Injections
60 builder.Injections
113 );
61 );
114 }
62 }
115
63
116 public void Visit(IInstanceRegistration registration) {
64 public void Visit(IInstanceRegistration registration) {
117 Safe.ArgumentNotNull(registration, nameof(registration));
65 Safe.ArgumentNotNull(registration, nameof(registration));
118
66
119 var registrationType = registration.GetRegistrationType(this);
67 var registrationType = registration.GetRegistrationType(this);
120
68
121 var builder = new InstanceRegistrationBuilder (
69 var builder = new InstanceRegistrationBuilder (
122 m_resolver,
70 m_resolver,
123 registrationType
71 registrationType
124 );
72 );
125
73
126 builder.Lifetime = registration.GetLifetime(this);
74 builder.Lifetime = registration.GetLifetime(this);
127
75
128 if (registration.MemberInjections != null) {
76 if (registration.MemberInjections != null) {
129 foreach(var member in registration.MemberInjections)
77 foreach(var member in registration.MemberInjections)
130 member.Visit(builder.ValueBuilder);
78 member.Visit(builder.ValueBuilder);
131 }
79 }
132
80
133 if (builder.RegistrationType == null && builder.ValueBuilder.ValueType == null)
81 if (builder.RegistrationType == null && builder.ValueBuilder.ValueType == null)
134 throw new Exception($"A type must be specified for the registration {registration.Name}");
82 throw new Exception($"A type must be specified for the registration {registration.Name}");
135
83
136 m_container.RegisterInstance(
84 m_container.RegisterInstance(
137 builder.RegistrationType ?? builder.ValueBuilder.ValueType,
85 builder.RegistrationType ?? builder.ValueBuilder.ValueType,
138 registration.Name,
86 registration.Name,
139 builder.ValueBuilder.Injection,
87 builder.ValueBuilder.Value,
140 builder.Lifetime
88 builder.Lifetime
141 );
89 );
142 }
90 }
143
91
144 public void Visit(IFactoryRegistration registration) {
145 Safe.ArgumentNotNull(registration, nameof(registration));
146
147 var registrationType = registration.GetRegistrationType(this);
148
149 var builder = new FactoryRegistrationBuilder(registrationType);
150
151 if (registration.MemberInjections != null) {
152 foreach(var member in registration.MemberInjections)
153 member?.Visit(builder);
154 }
155
156 }
157
158 public void AddNamespace(string ns) {
92 public void AddNamespace(string ns) {
159 m_resolver.AddNamespace(ns);
93 m_resolver.AddNamespace(ns);
160 }
94 }
161
95
162 public void AddAssembly(string assembly) {
96 public void AddAssembly(string assembly) {
163
97
164 }
98 }
165
99
166 public void Include(string file) {
100 public void Include(string file) {
167 var includeContext = new ContainerBuilder(m_container, m_schema);
101 var includeContext = new ContainerBuilder(m_container, m_schema);
168 includeContext.LoadConfig(file);
102 includeContext.LoadConfig(file);
169 }
103 }
170
104
171 public void LoadConfig(string file) {
105 public void LoadConfig(string file) {
172 var config = m_schema.LoadFile(file);
106 var config = m_schema.LoadFile(file);
173 config.Visit(this);
107 config.Visit(this);
174 }
108 }
175
109
176 }
110 }
177 } No newline at end of file
111 }
@@ -1,10 +1,12
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 void Visit(RegistrationBuilder builder) {
6 public override LifetimeManager GetLifetime(ContainerBuilder builder) {
7 builder.Visit(this);
7 return new ContainerControlledLifetimeManager();
8 }
8 }
9
10
9 }
11 }
10 } No newline at end of file
12 }
@@ -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 void Visit(RegistrationBuilder builder) {
6 public override LifetimeManager GetLifetime(ContainerBuilder builder) {
7 builder.Visist(this);
7 return new PerResolveLifetimeManager();
8 }
8 }
9 }
9 }
10 } No newline at end of file
10 }
@@ -1,17 +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 {
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(InjectionParameterBuilder builder) {
12 public override void Visit(InjectionParameterBuilder builder) {
13 var type = builder.ResolveInjectedValueType(TypeName);
13 var type = builder.ResolveInjectedValueType(TypeName);
14 builder.SetDependencyReference(type, DependencyName, Optional);
14 builder.SetDependency(type, DependencyName, Optional);
15 }
15 }
16 }
16 }
17 } No newline at end of file
17 }
@@ -1,29 +1,63
1 using System;
1 using System;
2 using System.Collections.Generic;
3 using System.Reflection;
4 using Implab.Components;
5 using Unity;
6 using Unity.Injection;
7 using Unity.Lifetime;
2
8
3 namespace Implab.ServiceHost.Unity {
9 namespace Implab.ServiceHost.Unity {
4 public class FactoryActivator : FactoryAbstractRegistratrion {
10 public class FactoryActivator : ITypeRegistration {
11
12 class FactoryInjector : ITypeMemberInjection {
13 public InjectionFactory Factory { get; set; }
14 public void Visit(TypeRegistrationBuilder builder) {
15 builder.AddInjectionMember(Factory);
16 }
17 }
18
5
19
6 public Type FactoryType { get; set; }
20 public Type FactoryType { get; set; }
7
21
8 public string FactoryName { get; set; }
22 public string FactoryName { get; set; }
9
23
10 public new Type RegistrationType { get; set; }
24 public Type RegistrationType { get; set; }
11
25
12 public override void Visit(FactoryRegistrationBuilder builder) {
26 public LifetimeManager Lifetime { get; set; }
13 base.Visit(builder);
14
27
15 builder.GetType()
28 public IEnumerable<ITypeMemberInjection> MemberInjections {
16 .GetMethod(
29 get {
17 nameof(FactoryRegistrationBuilder.SetFactoryDependency)
30 yield return new FactoryInjector {
18 , new[] { typeof(string) }
31 Factory = (InjectionFactory)GetType()
19 )
32 .GetMethod(nameof(CreateInjectionFactory), BindingFlags.Static | BindingFlags.NonPublic)
20 .MakeGenericMethod(FactoryType, RegistrationType)
33 .MakeGenericMethod(FactoryType, RegistrationType)
21 .Invoke(builder, new[] { FactoryName });
34 .Invoke(null, new [] { FactoryName })
35 };
36 }
22 }
37 }
23
38
24 public override Type GetRegistrationType(Func<string, Type> resolver) {
39 public string Name { get; set; }
40
41 public Type GetRegistrationType(ContainerBuilder builder) {
25 return RegistrationType;
42 return RegistrationType;
26 }
43 }
27
44
45 public LifetimeManager GetLifetime(ContainerBuilder builder) {
46 return Lifetime;
47 }
48
49 public Type GetImplementationType(ContainerBuilder builder) {
50 return null;
51 }
52
53 /// <summary>
54 /// Указывает зависимость, реализующую интерфейс <see cref="IFactory{TObj}"/>,
55 /// которая будет использоваться в качестве фабрики для создания объектов
56 /// </summary>
57 /// <param name="dependencyName"></param>
58 static InjectionFactory CreateInjectionFactory<TFac, TObj>(string dependencyName) where TFac : IFactory<TObj> {
59
60 return new InjectionFactory(c => c.Resolve<TFac>(dependencyName).Create());
61 }
28 }
62 }
29 } No newline at end of file
63 }
@@ -1,72 +1,72
1 using System;
1 using System;
2 using System.Xml.Serialization;
2 using System.Xml.Serialization;
3 using Implab.Components;
3 using Implab.Components;
4
4
5 namespace Implab.ServiceHost.Unity {
5 namespace Implab.ServiceHost.Unity {
6 /// <summary>
6 /// <summary>
7 /// Расширяет стандартную регистрацию типа до фабрики, вместе с регистрацией
7 /// Расширяет стандартную регистрацию типа до фабрики, вместе с регистрацией
8 /// самой фабрики создаются регистрации сервисов, которые она предоставляет.
8 /// самой фабрики создаются регистрации сервисов, которые она предоставляет.
9 /// </summary>
9 /// </summary>
10 public class FactoryElement : RegisterElement {
10 public class FactoryElement : RegisterElement, ITypeRegistration {
11
11
12 /// <summary>
12 /// <summary>
13 /// Записи о сервисах, которые создаются данной фабрикой.
13 /// Записи о сервисах, которые создаются данной фабрикой.
14 /// </summary>
14 /// </summary>
15 /// <remarks>
15 /// <remarks>
16 /// Сервисы, которые указаны в регистарциях они должны соответсвовать тому,
16 /// Сервисы, которые указаны в регистарциях они должны соответсвовать тому,
17 /// что фабрика возвращает, но это остается на откуп контейнера
17 /// что фабрика возвращает, но это остается на откуп контейнера
18 /// </remarks>
18 /// </remarks>
19 [XmlElement("provides")]
19 [XmlElement("provides")]
20 public ProvidesElement[] Provides { get; set; }
20 public ProvidesElement[] Provides { get; set; }
21
21
22 /// <summary>
22 /// <summary>
23 /// Переопределяет стандарное поведение регистрации типа в контейнере,
23 /// Переопределяет стандарное поведение регистрации типа в контейнере,
24 /// дополняя его регистрацией фабричных методов для получения типов.
24 /// дополняя его регистрацией фабричных методов для получения типов.
25 /// </summary>
25 /// </summary>
26 /// <param name="builder">Объект для конфигурирования контейнера.</param>
26 /// <param name="builder">Объект для конфигурирования контейнера.</param>
27 public override void Visit(ContainerBuilder builder) {
27 public override void Visit(ContainerBuilder builder) {
28 var factoryType = GetRegistrationType(builder.ResolveType);
28 var factoryType = GetRegistrationType(builder.ResolveType);
29
29
30 base.Visit(builder);
30 base.Visit(builder);
31
31
32 if (Provides != null && Provides.Length > 0) {
32 if (Provides != null && Provides.Length > 0) {
33 // если регистрации явно заданы, используеися информация из них
33 // если регистрации явно заданы, используеися информация из них
34 foreach(var item in Provides) {
34 foreach(var item in Provides) {
35 var activator = new FactoryActivator {
35 var activator = new FactoryActivator {
36 Name = item.RegistrationName,
36 Name = item.RegistrationName,
37 RegistrationType = builder.ResolveType(item.RegistrationType),
37 RegistrationType = builder.ResolveType(item.RegistrationType),
38 FactoryName = Name,
38 FactoryName = Name,
39 FactoryType = factoryType
39 FactoryType = factoryType
40 };
40 };
41 activator.Visit(builder);
41 builder.Visit(activator);
42 }
42 }
43 } else {
43 } else {
44 // если регистрация явно не задана, в качестве сервиса для регистрации
44 // если регистрация явно не задана, в качестве сервиса для регистрации
45 // используется тип создаваемый фабрикой, который будет добавлен в контейнер
45 // используется тип создаваемый фабрикой, который будет добавлен в контейнер
46 // с темже именем, что и сама фабрика (разные типы могут иметь одно имя для регистрации)
46 // с темже именем, что и сама фабрика (разные типы могут иметь одно имя для регистрации)
47 var providedType = (
47 var providedType = (
48 factoryType.IsGenericType && factoryType.GetGenericTypeDefinition() == typeof(IFactory<>) ?
48 factoryType.IsGenericType && factoryType.GetGenericTypeDefinition() == typeof(IFactory<>) ?
49 factoryType :
49 factoryType :
50 factoryType.GetInterface(typeof(IFactory<>).FullName)
50 factoryType.GetInterface(typeof(IFactory<>).FullName)
51 )?
51 )?
52 .GetGenericArguments()[0];
52 .GetGenericArguments()[0];
53
53
54 // не удалось определеить тип
54 // не удалось определеить тип
55 if (providedType == null)
55 if (providedType == null)
56 throw new ArgumentException("Failed to determine a type provided by the factory");
56 throw new ArgumentException("Failed to determine a type provided by the factory");
57
57
58 if (providedType.IsGenericParameter)
58 if (providedType.IsGenericParameter)
59 throw new ArgumentException("Can't register a generic type paramter as a service");
59 throw new ArgumentException("Can't register a generic type paramter as a service");
60
60
61 var activator = new FactoryActivator {
61 var activator = new FactoryActivator {
62 Name = Name,
62 Name = Name,
63 RegistrationType = providedType,
63 RegistrationType = providedType,
64 FactoryName = Name,
64 FactoryName = Name,
65 FactoryType = factoryType
65 FactoryType = factoryType
66 };
66 };
67
67
68 activator.Visit(builder);
68 builder.Visit(activator);
69 }
69 }
70 }
70 }
71 }
71 }
72 } No newline at end of file
72 }
@@ -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 void Visit(RegistrationBuilder builder) {
6 public override LifetimeManager GetLifetime(ContainerBuilder builder) {
7 builder.Visit(this);
7 return new HierarchicalLifetimeManager();
8 }
8 }
9 }
9 }
10 } No newline at end of file
10 }
@@ -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 {
5 public abstract class InjectionParameterElement : IInjectionParameter {
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(InjectionParameterBuilder builder);
10 public abstract void Visit(InjectionParameterBuilder builder);
11 }
11 }
12 } No newline at end of file
12 }
@@ -1,92 +1,137
1 using System;
1 using System;
2 using System.Collections;
2 using System.Collections.Generic;
3 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.ComponentModel;
4 using System.Linq;
5 using System.Linq;
5 using System.Xml.Serialization;
6 using System.Xml.Serialization;
6 using Unity.Injection;
7 using Unity.Injection;
7
8
8 namespace Implab.ServiceHost.Unity {
9 namespace Implab.ServiceHost.Unity {
9
10
10 public class InjectionParameterBuilder {
11 public class InjectionParameterBuilder {
11
12
12 readonly TypeResolver m_resolver;
13 readonly TypeResolver m_resolver;
13
14
14 public Type DefaultType { get; private set; }
15 public Type DefaultType { get; private set; }
15
16
16 public Type ValueType { get; private set; }
17 public Type ValueType { get; private set; }
17
18
18 public object Value { get; set; }
19 object m_value;
19
20
20 internal InjectionParameterValue Injection {
21 public object Value {
21 get {
22 get {
22 if (Value != null)
23 if (!ValueSpecified)
23 return InjectionParameterValue.ToParameter(Value);
24 throw new InvalidOperationException("The regular value must be set (dependency or array are not situable in this context)");
25 return m_value;
26 }
27 }
28
29 public bool ValueSpecified { get; private set; }
30
31 InjectionParameterValue m_injection;
24
32
25 return new InjectionParameter(ValueType, null);
33 public InjectionParameterValue Injection {
34 get {
35 if (m_injection == null)
36 throw new InvalidOperationException("The injection parameter is not specified");
37 return m_injection;
26 }
38 }
27 }
39 }
28
40
41 public bool InjectionSpecified {
42 get { return m_injection != null; }
43 }
44
29 internal InjectionParameterBuilder(TypeResolver resolver, Type defaultType) {
45 internal InjectionParameterBuilder(TypeResolver resolver, Type defaultType) {
30 m_resolver = resolver;
46 m_resolver = resolver;
31 DefaultType = defaultType;
47 DefaultType = defaultType;
32 }
48 }
33
49
34 public Type ResolveInjectedValueType(string typeSpec) {
50 public Type ResolveInjectedValueType(string typeSpec) {
35 if (string.IsNullOrEmpty(typeSpec)) {
51 if (string.IsNullOrEmpty(typeSpec)) {
36 if (DefaultType == null)
52 if (DefaultType == null)
37 throw new Exception("The type must be specified");
53 throw new Exception("The type must be specified");
38 return DefaultType;
54 return DefaultType;
39 }
55 }
40 return m_resolver.Resolve(typeSpec, true);
56 return m_resolver.Resolve(typeSpec, true);
41 }
57 }
42
58
43 public Type ResolveType(string typeSpec) {
59 public Type ResolveType(string typeSpec) {
44 return m_resolver.Resolve(typeSpec, true);
60 return string.IsNullOrEmpty(typeSpec) ? null : m_resolver.Resolve(typeSpec, true);
45 }
61 }
46
62
47 public void SetValue(Type type, object value) {
63 public void SetValue(Type type, object value) {
64 Safe.ArgumentNotNull(type, nameof(type));
65
48 ValueType = type;
66 ValueType = type;
49 Value = value;
67 m_value = value;
68 ValueSpecified = true;
69
70 m_injection = new InjectionParameter(type, value);
50 }
71 }
51
72
52 public void SetValue<T>(T value) {
73 public void SetDependency(Type type, string name, bool optional) {
53 SetValue(typeof(T), value);
74 Safe.ArgumentNotNull(type, nameof(type));
54 }
55
75
56 public void SetDependencyReference(Type type, string name, bool optional) {
57 ValueType = type;
76 ValueType = type;
58 Value = optional ? (object)new OptionalParameter(type, name) : new ResolvedParameter(type, name);
77 ValueSpecified = false;
78 m_value = null;
79
80 m_injection = optional ? (InjectionParameterValue)new OptionalParameter(type, name) : new ResolvedParameter(type, name);
59 }
81 }
60
82
61 internal void Visit(ArrayParameterElement arrayParameter) {
83 internal void Visit(ArrayParameterElement arrayParameter) {
62 Type itemsType = null;
84 Type itemsType = null;
63 var arrayType = string.IsNullOrEmpty(arrayParameter.TypeName) ? null : ResolveType(arrayParameter.TypeName);
85 var arrayType = string.IsNullOrEmpty(arrayParameter.TypeName) ? null : ResolveType(arrayParameter.TypeName);
64
86
87 if (arrayType == null)
88 arrayType = DefaultType;
89
90
65 if (!string.IsNullOrEmpty(arrayParameter.ItemsType)) {
91 if (!string.IsNullOrEmpty(arrayParameter.ItemsType)) {
66 itemsType = ResolveType(arrayParameter.ItemsType);
92 itemsType = ResolveType(arrayParameter.ItemsType);
67 if (arrayType == null)
68 arrayType = itemsType.MakeArrayType();
93 arrayType = itemsType.MakeArrayType();
69 } else {
94 } else {
70 itemsType = arrayType?.GetInterface(typeof(IEnumerable<>).FullName)?.GetGenericArguments()[0];
95 itemsType = GetItemsType(arrayType);
71 }
96 }
72
97
73 if (itemsType == null)
98 if (itemsType == null)
74 throw new Exception("Failed to determine array elements type");
99 throw new Exception("Failed to determine array elements type");
75
100
76 InjectionParameterValue[] injections = (arrayParameter.Items ?? new InjectionParameterElement[0])
101 InjectionParameterValue[] injections = (arrayParameter.Items ?? new InjectionParameterElement[0])
77 .Select(x => {
102 .Select(x => {
78 var builder = new InjectionParameterBuilder(m_resolver, itemsType);
103 var builder = new InjectionParameterBuilder(m_resolver, itemsType);
79 x.Visit(builder);
104 x.Visit(builder);
80 return builder.Injection;
105 return builder.Injection;
81 })
106 })
82 .ToArray();
107 .ToArray();
83
108
84 var array = itemsType.IsGenericParameter ?
109 var array = itemsType.IsGenericParameter ?
85 (object)new GenericResolvedArrayParameter(itemsType.Name, injections) :
110 (InjectionParameterValue)new GenericResolvedArrayParameter(itemsType.Name, injections) :
86 new ResolvedArrayParameter(itemsType, injections);
111 new ResolvedArrayParameter(itemsType, injections);
87
112
88 ValueType = arrayType;
113 ValueType = arrayType;
89 Value = array;
114 m_value = null;
115 ValueSpecified = false;
116
117 m_injection = array;
118 }
119
120 Type GetItemsType(Type collectionType) {
121 if (collectionType == null)
122 return null;
123
124 Type itemsType = null;
125
126 if (collectionType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) {
127 itemsType = collectionType.GetGenericArguments()[0];
128 } else if (collectionType == typeof(IEnumerable)) {
129 itemsType = typeof(object);
130 } else {
131 itemsType = collectionType.GetInterface(typeof(IEnumerable<>).FullName)?.GetGenericArguments()[0];
132 }
133
134 return itemsType;
90 }
135 }
91 }
136 }
92 } No newline at end of file
137 }
@@ -1,5 +1,7
1 using Unity.Lifetime;
2
1 namespace Implab.ServiceHost.Unity {
3 namespace Implab.ServiceHost.Unity {
2 public abstract class LifetimeElement {
4 public abstract class LifetimeElement {
3 public abstract void Visit(RegistrationBuilder builder);
5 public abstract LifetimeManager GetLifetime(ContainerBuilder builder);
4 }
6 }
5 } No newline at end of file
7 }
@@ -1,20 +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 : AbstractMemberInjection {
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 [XmlElement("array", typeof(ArrayParameterElement))]
14 public InjectionParameterElement[] Parameters { get; set; }
14 public InjectionParameterElement[] Parameters { get; set; }
15
15
16 internal override void Visit(TypeRegistrationBuilder context) {
16 public override void Visit(TypeRegistrationBuilder context) {
17 context.Visit(this);
17 context.Visit(this);
18 }
18 }
19 }
19 }
20 } No newline at end of file
20 }
@@ -1,20 +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 : AbstractMemberInjection {
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 [XmlElement("array", typeof(ArrayParameterElement))]
14 public InjectionParameterElement Value { get; set; }
14 public InjectionParameterElement Value { get; set; }
15
15
16 internal override void Visit(TypeRegistrationBuilder context) {
16 public override void Visit(TypeRegistrationBuilder context) {
17 context.Visit(this);
17 context.Visit(this);
18 }
18 }
19 }
19 }
20 } No newline at end of file
20 }
@@ -1,36 +1,39
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Xml.Serialization;
3 using System.Xml.Serialization;
3 using Unity.Lifetime;
4 using Unity.Lifetime;
4 using Unity.Registration;
5 using Unity.Registration;
5
6
6 namespace Implab.ServiceHost.Unity {
7 namespace Implab.ServiceHost.Unity {
7
8
8 [XmlRoot("register", Namespace = Schema.ContainerConfigurationNamespace)]
9 [XmlRoot("register", Namespace = Schema.ContainerConfigurationNamespace)]
9 public class RegisterElement : TypeAbstractRegistration {
10 public class RegisterElement : AbstractRegistration, ITypeRegistration {
10
11
11 /// <summary>
12 /// <summary>
12 /// An optional type which is registered as a service in the container, must be assignable to <see cref="ProvidesType">.
13 /// An optional type which is registered as a service in the container, must be assignable to <see cref="ProvidesType">.
13 /// </summary>
14 /// </summary>
14 [XmlAttribute("mapTo")]
15 [XmlAttribute("mapTo")]
15 public string MapToType { get; set; }
16 public string MapToType { get; set; }
16
17
17
18
18 [XmlElement("constructor", typeof(ConstructorInjectionElement))]
19 [XmlElement("constructor", typeof(ConstructorInjectionElement))]
19 [XmlElement("property", typeof(PropertyInjectionElement))]
20 [XmlElement("property", typeof(PropertyInjectionElement))]
20 [XmlElement("method", typeof(MethodInjectionElement))]
21 [XmlElement("method", typeof(MethodInjectionElement))]
21 public AbstractMemberInjection[] Injectors { get; set; }
22 public AbstractMemberInjection[] Injectors { get; set; }
22
23
23 public override Type GetImplementationType(Func<string, Type> resolver) {
24 IEnumerable<ITypeMemberInjection> ITypeRegistration.MemberInjections {
24 return string.IsNullOrEmpty(MapToType) ? null : resolver(MapToType);
25 get {
26 return Injectors;
27 }
25 }
28 }
26
29
27 public override void Visit(TypeRegistrationBuilder builder) {
30 public Type GetImplementationType(ContainerBuilder builder) {
28 if(Injectors != null)
31 return builder.ResolveType(MapToType);
29 foreach(var injector in Injectors)
30 injector.Visit(builder);
31 }
32 }
32
33
33
34 public override void Visit(ContainerBuilder builder) {
35 builder.Visit(this);
36 }
34 }
37 }
35
38
36 } No newline at end of file
39 }
@@ -1,29 +1,32
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Xml;
3 using System.Xml;
3 using System.Xml.Serialization;
4 using System.Xml.Serialization;
4
5
5 namespace Implab.ServiceHost.Unity
6 namespace Implab.ServiceHost.Unity {
6 {
7 public class SerializedElement : AbstractRegistration, IInstanceRegistration {
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 public override void Visit(InstanceRegistrationBuilder builder) {
18 public IEnumerable<IInjectionParameter> MemberInjections {
19 base.Visit(builder);
19 get {
20
20 yield return new SerializedParameterElement {
21 var parameter = new SerializedParameterElement {
22 TypeName = SerializedType,
21 TypeName = SerializedType,
23 Location = Location,
22 Location = Location,
24 Content = Content
23 Content = Content
25 };
24 };
26 parameter.Visit(builder.ValueBuilder);
25 }
26 }
27
28 public override void Visit(ContainerBuilder builder) {
29 builder.Visit(this);
27 }
30 }
28 }
31 }
29 } No newline at end of file
32 }
@@ -1,8 +1,10
1 using Unity.Lifetime;
2
1 namespace Implab.ServiceHost.Unity
3 namespace Implab.ServiceHost.Unity
2 {
4 {
3 public class SingletonLifetimeElement : LifetimeElement {
5 public class SingletonLifetimeElement : LifetimeElement {
4 public override void Visit(RegistrationBuilder builder) {
6 public override LifetimeManager GetLifetime(ContainerBuilder builder) {
5 builder.Visit(this);
7 return new SingletonLifetimeManager();
6 }
8 }
7 }
9 }
8 } No newline at end of file
10 }
@@ -1,75 +1,81
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 internal 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 InjectionParameterBuilder(m_resolver, null);
40 var valueBuilder = new InjectionParameterBuilder(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 parameters = methodInjection.Parameters?
51 var parameters = methodInjection.Parameters?
52 .Select(x => {
52 .Select(x => {
53 var valueBuilder = new InjectionParameterBuilder(m_resolver, null);
53 var valueBuilder = new InjectionParameterBuilder(m_resolver, null);
54 x.Visit(valueBuilder);
54 x.Visit(valueBuilder);
55 return valueBuilder.Injection;
55 return valueBuilder.Injection;
56 })
56 })
57 .ToArray();
57 .ToArray();
58
58
59 var injection = parameters != null ? new InjectionMethod(methodInjection.Name, parameters) : new InjectionMethod(methodInjection.Name);
59 var injection = parameters != null ? new InjectionMethod(methodInjection.Name, parameters) : new InjectionMethod(methodInjection.Name);
60 m_injections.Add(injection);
60 m_injections.Add(injection);
61 }
61 }
62
62
63 internal void Visit(PropertyInjectionElement propertyInjection) {
63 internal void Visit(PropertyInjectionElement propertyInjection) {
64 if (propertyInjection.Value == null)
64 if (propertyInjection.Value == null)
65 throw new Exception($"A value value must be specified for the property '{propertyInjection.Name}'");
65 throw new Exception($"A value value must be specified for the property '{propertyInjection.Name}'");
66
66
67 var propertyType = ImplementationType.GetProperty(propertyInjection.Name)?.PropertyType;
67 var propertyType = ImplementationType.GetProperty(propertyInjection.Name)?.PropertyType;
68 var valueContext = new InjectionParameterBuilder(m_resolver, propertyType);
68 var valueContext = new InjectionParameterBuilder(m_resolver, propertyType);
69
69
70 propertyInjection.Value.Visit(valueContext);
70 propertyInjection.Value.Visit(valueContext);
71 var injection = new InjectionProperty(propertyInjection.Name, valueContext.Injection);
71 var injection = new InjectionProperty(propertyInjection.Name, valueContext.Injection);
72 m_injections.Add(injection);
72 m_injections.Add(injection);
73 }
73 }
74
75 public void AddInjectionMember(InjectionMember injection) {
76 Safe.ArgumentNotNull(injection, nameof(injection));
77
78 m_injections.Add(injection);
79 }
74 }
80 }
75 } No newline at end of file
81 }
@@ -1,98 +1,99
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 using System.Diagnostics;
9 using System.Diagnostics;
10 using static Trace<TypeResolver>;
10 using static Trace<TypeResolver>;
11 public class TypeResolver {
11 public class TypeResolver {
12 readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>();
12 readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>();
13
13
14 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
14 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
15 readonly LinkedList<string> m_namespases = new LinkedList<string>();
15 readonly LinkedList<string> m_namespases = new LinkedList<string>();
16
16
17 internal Type Resolve(string ns, string typeName) {
17 internal Type Resolve(string ns, string typeName) {
18 var fullName = string.IsNullOrEmpty(ns) ? typeName : $"{ns}.{typeName}";
18 var fullName = string.IsNullOrEmpty(ns) ? typeName : $"{ns}.{typeName}";
19
19
20 return ProbeInNamespaces(fullName);
20 return ProbeInNamespaces(fullName);
21 }
21 }
22
22
23 public Type Resolve(TypeReference typeReference, bool throwOnFail) {
23 public Type Resolve(TypeReference typeReference, bool throwOnFail) {
24 var context = new TypeResolutionContext(this, throwOnFail);
24 var context = new TypeResolutionContext(this, throwOnFail);
25 typeReference.Visit(context);
25 typeReference.Visit(context);
26 return context.MakeType();
26 return context.MakeType();
27 }
27 }
28
28
29 public Type Resolve(string typeSpec, bool throwOnFail) {
29 public Type Resolve(string typeSpec, bool throwOnFail) {
30 Safe.ArgumentNotEmpty(typeSpec, nameof(typeSpec));
30 var typeReference = TypeReference.Parse(typeSpec);
31 var typeReference = TypeReference.Parse(typeSpec);
31 return Resolve(typeReference, throwOnFail);
32 return Resolve(typeReference, throwOnFail);
32 }
33 }
33
34
34 LinkedListNode<string> m_insertAt;
35 LinkedListNode<string> m_insertAt;
35
36
36 readonly TypeResolver m_parent;
37 readonly TypeResolver m_parent;
37
38
38 public TypeResolver() : this(null) {
39 public TypeResolver() : this(null) {
39 }
40 }
40
41
41 public TypeResolver(TypeResolver parent) {
42 public TypeResolver(TypeResolver parent) {
42 m_parent = parent;
43 m_parent = parent;
43 m_insertAt = new LinkedListNode<string>(string.Empty);
44 m_insertAt = new LinkedListNode<string>(string.Empty);
44 m_namespases.AddFirst(m_insertAt);
45 m_namespases.AddFirst(m_insertAt);
45 }
46 }
46
47
47 public void AddNamespace(string ns) {
48 public void AddNamespace(string ns) {
48 Safe.ArgumentMatch(ns, nameof(ns), _nsRx);
49 Safe.ArgumentMatch(ns, nameof(ns), _nsRx);
49 if (m_insertAt != null)
50 if (m_insertAt != null)
50 m_namespases.AddAfter(m_insertAt, ns);
51 m_namespases.AddAfter(m_insertAt, ns);
51 else
52 else
52 m_namespases.AddFirst(ns);
53 m_namespases.AddFirst(ns);
53 }
54 }
54
55
55 public void AddMapping(string typeName, Type type) {
56 public void AddMapping(string typeName, Type type) {
56 Safe.ArgumentNotEmpty(typeName, nameof(typeName));
57 Safe.ArgumentNotEmpty(typeName, nameof(typeName));
57 Safe.ArgumentNotNull(type, nameof(type));
58 Safe.ArgumentNotNull(type, nameof(type));
58
59
59 m_cache[typeName] = type;
60 m_cache[typeName] = type;
60 }
61 }
61
62
62 Type ProbeInNamespaces(string localName) {
63 Type ProbeInNamespaces(string localName) {
63
64
64 Type resolved;
65 Type resolved;
65 if (!m_cache.TryGetValue(localName, out resolved)) {
66 if (!m_cache.TryGetValue(localName, out resolved)) {
66 foreach (var ns in m_namespases) {
67 foreach (var ns in m_namespases) {
67 var typeName = string.IsNullOrEmpty(ns) ? localName : $"{ns}.{localName}";
68 var typeName = string.IsNullOrEmpty(ns) ? localName : $"{ns}.{localName}";
68 resolved = Probe(typeName);
69 resolved = Probe(typeName);
69 if (resolved != null) {
70 if (resolved != null) {
70 Log($"Probe '{localName}' -> '{resolved.FullName}'");
71 Log($"Probe '{localName}' -> '{resolved.FullName}'");
71 break;
72 break;
72 }
73 }
73 }
74 }
74
75
75 if (resolved == null && m_parent != null)
76 if (resolved == null && m_parent != null)
76 resolved = m_parent.ProbeInNamespaces(localName);
77 resolved = m_parent.ProbeInNamespaces(localName);
77
78
78 if(resolved == null)
79 if(resolved == null)
79 Log($"Probe '{localName}' failed");
80 Log($"Probe '{localName}' failed");
80
81
81 m_cache[localName] = resolved;
82 m_cache[localName] = resolved;
82 }
83 }
83
84
84 return resolved;
85 return resolved;
85 }
86 }
86
87
87 Type Probe(string typeName) {
88 Type Probe(string typeName) {
88 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
89 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
89
90
90 foreach (var assembly in assemblies) {
91 foreach (var assembly in assemblies) {
91 var type = assembly.GetType(typeName);
92 var type = assembly.GetType(typeName);
92 if (type != null)
93 if (type != null)
93 return type;
94 return type;
94 }
95 }
95 return null;
96 return null;
96 }
97 }
97 }
98 }
98 } No newline at end of file
99 }
@@ -1,31 +1,36
1 using System.Collections.Generic;
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 ValueElement : InstanceAbstractRegistration {
5 public class ValueElement : AbstractRegistration, IInstanceRegistration {
5
6
6 [XmlAttribute("value")]
7 [XmlAttribute("value")]
7 public string Value { get; set; }
8 public string Value { get; set; }
8
9
9 [XmlText]
10 [XmlText]
10 public string Text { get; set; }
11 public string Text { get; set; }
11
12
12 string GetTextValue() {
13 string GetTextValue() {
13 return string.IsNullOrEmpty(Value) ? Text : Value;
14 return string.IsNullOrEmpty(Value) ? Text : Value;
14 }
15 }
15
16
16 public string TypeName {
17 public string TypeName {
17 get {
18 get {
18 return RegistrationType;
19 return RegistrationType;
19 }
20 }
20 }
21 }
21
22
22 public override void Visit(InstanceRegistrationBuilder builder) {
23 public IEnumerable<IInjectionParameter> MemberInjections {
23 base.Visit(builder);
24 get {
24 var parameter = new ValueParameterElement {
25 yield return new ValueParameterElement {
25 Value = Value,
26 Value = Value,
26 Text = Text
27 Text = Text
27 };
28 };
28 parameter.Visit(builder.ValueBuilder);
29 }
30 }
31
32 public override void Visit(ContainerBuilder builder) {
33 builder.Visit(this);
29 }
34 }
30 }
35 }
31 } No newline at end of file
36 }
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
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