##// 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,4 +1,5
1 1 using System;
2 using System.Collections.Generic;
2 3 using System.Diagnostics;
3 4 using System.Linq;
4 5 using Implab.Diagnostics;
@@ -22,6 +23,10 namespace Implab.Playground {
22 23
23 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 32 public interface IContainer<T> {
@@ -42,30 +47,44 namespace Implab.Playground {
42 47 public void SetInstance(T value) {
43 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 60 public class Program {
48 61
49 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 68 var stopwatch = new Stopwatch();
51 69 stopwatch.Start();
52 70
53 71 var ctx = new ContainerBuilder();
54 72
55 73 Console.WriteLine($"Created: {stopwatch.ElapsedMilliseconds}");
56
74 stopwatch.Restart();
75
57 76 ctx.LoadConfig("data/sample.xml");
58 77
59 78 Console.WriteLine($"Loaded: {stopwatch.ElapsedMilliseconds}");
60 79
61 80 var container = ctx.Container;
62 81
63
64
82 stopwatch.Restart();
65 83 var instace1 = container.Resolve<IContainer<string>>();
66 84 Console.WriteLine($"Resolved1: {stopwatch.ElapsedMilliseconds}");
85
86 stopwatch.Restart();
67 87 var instace2 = container.Resolve<IContainer<Foo>>();
68
69 88 Console.WriteLine($"Resolved2: {stopwatch.ElapsedMilliseconds}");
70 89
71 90 DisplayContainerRegistrations(container);
@@ -1,6 +1,7
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <container xmlns="http://implab.org/schemas/servicehost/unity.v1.xsd">
3 3 <namespace name="System"/>
4 <namespace name="System.Collections.Generic"/>
4 5 <namespace name="Implab.Playground"/>
5 6
6 7 <!-- foo1 -->
@@ -21,6 +22,11
21 22 </register>
22 23
23 24 <register type="Foo">
25 <method name="AddRange">
26 <array itemsType="Foo">
27 <dependency name="foo2"/>
28 </array>
29 </method>
24 30 </register>
25 31
26 32 <register type="IContainer{}" mapTo="Container{}">
@@ -28,6 +34,15
28 34 <method name="SetInstance">
29 35 <dependency type="T"/>
30 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 46 </register>
32 47
33 48 <register type="IContainer{String}" mapTo="Container{String}">
@@ -46,4 +61,8
46 61 <value name="connection1" type="String"><![CDATA[Connect me <here>!]]></value>
47 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 68 </container> No newline at end of file
@@ -4,7 +4,7 namespace Implab.ServiceHost.Unity {
4 4 /// <summary>
5 5 /// Base class for injections, each injection is applied to the type registration context.
6 6 /// </summary>
7 public abstract class AbstractInjectionElement {
7 public abstract class AbstractMemberInjection {
8 8 internal abstract void Visit(TypeRegistrationBuilder context);
9 9 }
10 10 } No newline at end of file
@@ -5,7 +5,10 using Unity.Registration;
5 5
6 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 13 /// <summary>
11 14 /// An optional name for a registration in the container
@@ -15,7 +18,7 namespace Implab.ServiceHost.Unity
15 18 get; set;
16 19 }
17 20
18 [XmlElement("signleton", typeof(SimgletonLifetimeElement))]
21 [XmlElement("signleton", typeof(SingletonLifetimeElement))]
19 22 [XmlElement("context", typeof(ContextLifetimeElement))]
20 23 [XmlElement("container", typeof(ContainerLifetimeElement))]
21 24 [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
@@ -27,5 +30,13 namespace Implab.ServiceHost.Unity
27 30 [XmlAttribute("type")]
28 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 42 } No newline at end of file
@@ -3,12 +3,12 using System.Xml.Serialization;
3 3 namespace Implab.ServiceHost.Unity
4 4 {
5 5 [XmlRoot("assembly", Namespace = Schema.ContainerConfigurationNamespace)]
6 public class AssemblyElement : ContainerItemElement {
6 public class AssemblyElement : AbstractContainerItem {
7 7 [XmlAttribute("name")]
8 8 public string AssemblyName { get; set; }
9 9
10 public override void Visit(ContainerBuilder context) {
11 context.Visit(this);
10 public override void Visit(ContainerBuilder builder) {
11 builder.Visit(this);
12 12 }
13 13 }
14 14 } No newline at end of file
@@ -1,12 +1,13
1 1 using System.Xml.Serialization;
2 2
3 3 namespace Implab.ServiceHost.Unity {
4 public class ConstructorInjectionElement : AbstractInjectionElement {
4 public class ConstructorInjectionElement : AbstractMemberInjection {
5 5
6 6 [XmlElement("dependency", typeof(DependencyParameterElement))]
7 7 [XmlElement("value", typeof(ValueParameterElement))]
8 8 [XmlElement("serialized", typeof(SerializedParameterElement))]
9 9 [XmlElement("default", typeof(DefaultParameterElement))]
10 [XmlElement("array", typeof(ArrayParameterElement))]
10 11 public InjectionParameterElement[] Parameters { get; set; }
11 12
12 13 internal override void Visit(TypeRegistrationBuilder context) {
@@ -39,9 +39,10 namespace Implab.ServiceHost.Unity {
39 39 return m_resolver.Resolve(typeReference);
40 40 }
41 41
42 internal void Visit(RegisterElement registerElement) {
43 var registrationType = ResolveType(registerElement.RegistrationType);
44 var implementationType = string.IsNullOrEmpty(registerElement.MapToType) ? registrationType : ResolveType(registerElement.MapToType);
42
43 internal void Visit(TypeAbstractRegistration typeRegistration) {
44 var registrationType = typeRegistration.GetRegistrationType(ResolveType);
45 var implementationType = typeRegistration.GetImplementationType(ResolveType) ?? registrationType;
45 46
46 47 var registrationContext = new TypeRegistrationBuilder(
47 48 m_resolver,
@@ -49,46 +50,44 namespace Implab.ServiceHost.Unity {
49 50 implementationType
50 51 );
51 52
52 if (registerElement.Injectors != null) {
53 foreach (var injector in registerElement.Injectors) {
54 injector.Visit(registrationContext);
55 }
56 }
53 typeRegistration.Visit(registrationContext);
57 54
58 55 m_container.RegisterType(
59 56 registrationContext.RegistrationType,
60 57 registrationContext.ImplementationType,
61 registerElement.Name,
62 registerElement.Lifetime?.GetLifetimeManager(this),
58 typeRegistration.Name,
59 registrationContext.Lifetime,
63 60 registrationContext.Injections
64 61 );
65 62 }
66 63
67 internal void Visit(SerializedElement serializedElement) {
68 var registrationType = ResolveType(serializedElement.RegistrationType);
69 var valueBuilder = new InjectionValueBuilder(m_resolver, null);
64 internal void Visit(InstanceAbstractRegistration instanceRegistration) {
65 var registrationType = instanceRegistration.GetRegistrationType(ResolveType);
66
67 var builder = new InstanceRegistrationBuilder(m_resolver, registrationType);
70 68
71 valueBuilder.Visit(serializedElement);
72
69 instanceRegistration.Visit(builder);
70
73 71 m_container.RegisterInstance(
74 registrationType,
75 serializedElement.Name,
76 valueBuilder.Value,
77 serializedElement.Lifetime?.GetLifetimeManager(this)
72 builder.ValueBuilder.ValueType,
73 instanceRegistration.Name,
74 builder.ValueBuilder.Value,
75 builder.Lifetime
78 76 );
79 77 }
80 78
81 internal void Visit(ValueElement valueElement) {
82 var registrationType = ResolveType(valueElement.RegistrationType);
83 var valueBuilder = new InjectionValueBuilder(m_resolver, null);
79 internal void Visit(FactoryAbstractRegistratrion factoryRgistration) {
80 var registrationType = factoryRgistration.GetRegistrationType(ResolveType);
81
82 var builder = new FactoryRegistrationBuilder(registrationType);
84 83
85 valueBuilder.Visit(valueElement);
86
87 m_container.RegisterInstance(
88 registrationType,
89 valueElement.Name,
90 valueBuilder.Value,
91 valueElement.Lifetime?.GetLifetimeManager(this)
84 factoryRgistration.Visit(builder);
85
86 m_container.RegisterType(
87 builder.RegistrationType,
88 factoryRgistration.Name,
89 builder.Lifetime,
90 builder.Factory
92 91 );
93 92 }
94 93
@@ -111,15 +110,9 namespace Implab.ServiceHost.Unity {
111 110
112 111 public void LoadConfig(string file) {
113 112 var config = m_schema.LoadFile(file);
114 Visit(config);
113
114 config.Visit(this);
115 115 }
116
117 internal void Visit(ContainerElement containerElement) {
118 foreach (var item in containerElement.Items)
119 item.Visit(this);
120 }
121
122
123
116
124 117 }
125 118 } No newline at end of file
@@ -33,15 +33,15 namespace Implab.ServiceHost.Unity {
33 33 Safe.ArgumentNotNull(type, nameof(type));
34 34 Safe.ArgumentNotEmpty(name, nameof(name));
35 35
36 if(!type.IsSubclassOf(typeof(ContainerItemElement)))
37 throw new Exception($"RegisterContainerElement '{name}': {type} must be subclass of {typeof(ContainerItemElement)}");
36 if(!type.IsSubclassOf(typeof(AbstractContainerItem)))
37 throw new Exception($"RegisterContainerElement '{name}': {type} must be subclass of {typeof(AbstractContainerItem)}");
38 38
39 39 m_containerItems.XmlElements.Add(
40 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 45 RegisterContainerElement(typeof(T), name);
46 46 }
47 47
@@ -6,12 +6,14 using System.Xml.Serialization;
6 6
7 7 namespace Implab.ServiceHost.Unity {
8 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 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 19 } No newline at end of file
@@ -3,8 +3,8 using Unity.Lifetime;
3 3 namespace Implab.ServiceHost.Unity
4 4 {
5 5 public class ContainerLifetimeElement : LifetimeElement {
6 public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
7 return new ContainerControlledLifetimeManager();
6 public override void Visit(RegistrationBuilder builder) {
7 builder.Visit(this);
8 8 }
9 9 }
10 10 } No newline at end of file
@@ -3,8 +3,8 using Unity.Lifetime;
3 3 namespace Implab.ServiceHost.Unity
4 4 {
5 5 public class ContextLifetimeElement : LifetimeElement {
6 public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
7 return new PerResolveLifetimeManager();
6 public override void Visit(RegistrationBuilder builder) {
7 builder.Visist(this);
8 8 }
9 9 }
10 10 } No newline at end of file
@@ -1,12 +1,13
1 1 namespace Implab.ServiceHost.Unity
2 2 {
3 public class DefaultParameterElement : InjectionParameterElement, ITextValue {
3 public class DefaultParameterElement : InjectionParameterElement {
4 4 public string Value {
5 5 get { return null; }
6 6 }
7 7
8 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 13 } No newline at end of file
@@ -1,7 +1,7
1 1 using System.Xml.Serialization;
2 2
3 3 namespace Implab.ServiceHost.Unity {
4 public class DependencyParameterElement : InjectionParameterElement, IDependencyReference {
4 public class DependencyParameterElement : InjectionParameterElement {
5 5
6 6 [XmlAttribute("name")]
7 7 public string DependencyName { get; set; }
@@ -10,7 +10,8 namespace Implab.ServiceHost.Unity {
10 10 public bool Optional { get; set; }
11 11
12 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 17 } No newline at end of file
@@ -3,8 +3,8 using Unity.Lifetime;
3 3 namespace Implab.ServiceHost.Unity
4 4 {
5 5 public class HierarchicalLifetimeElement : LifetimeElement {
6 public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
7 return new HierarchicalLifetimeManager();
6 public override void Visit(RegistrationBuilder builder) {
7 builder.Visit(this);
8 8 }
9 9 }
10 10 } No newline at end of file
@@ -2,7 +2,7 using System.Xml.Serialization;
2 2
3 3 namespace Implab.ServiceHost.Unity {
4 4 [XmlRoot("include", Namespace = Schema.ContainerConfigurationNamespace)]
5 public class IncludeElement : ContainerItemElement {
5 public class IncludeElement : AbstractContainerItem {
6 6 [XmlAttribute("href")]
7 7 public string Href { get; set; }
8 8
@@ -2,7 +2,7 using System;
2 2 using System.Xml.Serialization;
3 3
4 4 namespace Implab.ServiceHost.Unity {
5 public abstract class InjectionParameterElement : IInjectionParameter {
5 public abstract class InjectionParameterElement {
6 6
7 7 [XmlAttribute("type")]
8 8 public string TypeName { get; set; }
@@ -1,5 +1,7
1 1 using System;
2 using System.Collections.Generic;
2 3 using System.ComponentModel;
4 using System.Linq;
3 5 using System.Xml.Serialization;
4 6 using Unity.Injection;
5 7
@@ -11,11 +13,11 namespace Implab.ServiceHost.Unity {
11 13
12 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 18 public object Value { get; set; }
17 19
18 public InjectionParameterValue Injection {
20 internal InjectionParameterValue Injection {
19 21 get {
20 22 if (Value != null)
21 23 return InjectionParameterValue.ToParameter(Value);
@@ -24,12 +26,12 namespace Implab.ServiceHost.Unity {
24 26 }
25 27 }
26 28
27 internal InjectionValueBuilder(TypeResolver resolver, Type acceptsType) {
29 internal InjectionValueBuilder(TypeResolver resolver, Type defaultType) {
28 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 35 if (string.IsNullOrEmpty(typeSpec)) {
34 36 if (DefaultType == null)
35 37 throw new Exception("The type must be specified");
@@ -38,27 +40,50 namespace Implab.ServiceHost.Unity {
38 40 return m_resolver.Resolve(typeSpec);
39 41 }
40 42
41 public void Visit(ITextValue value) {
42 ValueType = ResolveType(value.TypeName);
43 public Type ResolveType(string typeSpec) {
44 return m_resolver.Resolve(typeSpec);
45 }
43 46
44 Value = string.IsNullOrEmpty(value.Value) ?
45 Safe.CreateDefaultValue(ValueType) :
46 TypeDescriptor.GetConverter(ValueType).ConvertFromString(value.Value);
47 public void SetValue(Type type, object value) {
48 ValueType = type;
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) {
50 ValueType = ResolveType(value.TypeName);
61 internal void Visit(ArrayParameterElement arrayParameter) {
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())
55 Value = new InjectionParameter(ValueType, serializer.Deserialize(reader));
56 }
73 if (itemsType == null)
74 throw new Exception("Failed to determine array elements type");
57 75
58 public void Visit(IDependencyReference value) {
59 ValueType = ResolveType(value.TypeName);
60 Value = new ResolvedParameter(ValueType, value.DependencyName);
76 InjectionParameterValue[] injections = (arrayParameter.Items ?? new InjectionParameterElement[0])
77 .Select(x => {
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 89 } No newline at end of file
@@ -1,10 +1,5
1 using Unity.Lifetime;
2
3 namespace Implab.ServiceHost.Unity
4 {
5 public abstract class LifetimeElement
6 {
7 public abstract LifetimeManager GetLifetimeManager(ContainerBuilder ctx);
8
1 namespace Implab.ServiceHost.Unity {
2 public abstract class LifetimeElement {
3 public abstract void Visit(RegistrationBuilder builder);
9 4 }
10 5 } No newline at end of file
@@ -1,7 +1,7
1 1 using System.Xml.Serialization;
2 2
3 3 namespace Implab.ServiceHost.Unity {
4 public class MethodInjectionElement : AbstractInjectionElement {
4 public class MethodInjectionElement : AbstractMemberInjection {
5 5
6 6 [XmlAttribute("name")]
7 7 public string Name { get; set; }
@@ -10,6 +10,7 namespace Implab.ServiceHost.Unity {
10 10 [XmlElement("value", typeof(ValueParameterElement))]
11 11 [XmlElement("serialized", typeof(SerializedParameterElement))]
12 12 [XmlElement("default", typeof(DefaultParameterElement))]
13 [XmlElement("array", typeof(ArrayParameterElement))]
13 14 public InjectionParameterElement[] Parameters { get; set; }
14 15
15 16 internal override void Visit(TypeRegistrationBuilder context) {
@@ -3,7 +3,7 using System.Xml.Serialization;
3 3 namespace Implab.ServiceHost.Unity
4 4 {
5 5 [XmlRoot("namespace", Namespace = Schema.ContainerConfigurationNamespace)]
6 public class NamespaceElement : ContainerItemElement {
6 public class NamespaceElement : AbstractContainerItem {
7 7
8 8 [XmlAttribute("name")]
9 9 public string Name { get; set; }
@@ -1,7 +1,7
1 1 using System.Xml.Serialization;
2 2
3 3 namespace Implab.ServiceHost.Unity {
4 public class PropertyInjectionElement : AbstractInjectionElement {
4 public class PropertyInjectionElement : AbstractMemberInjection {
5 5
6 6 [XmlAttribute("name")]
7 7 public string Name { get; set; }
@@ -10,6 +10,7 namespace Implab.ServiceHost.Unity {
10 10 [XmlElement("value", typeof(ValueParameterElement))]
11 11 [XmlElement("serialized", typeof(SerializedParameterElement))]
12 12 [XmlElement("default", typeof(DefaultParameterElement))]
13 [XmlElement("array", typeof(ArrayParameterElement))]
13 14 public InjectionParameterElement Value { get; set; }
14 15
15 16 internal override void Visit(TypeRegistrationBuilder context) {
@@ -6,7 +6,7 using Unity.Registration;
6 6 namespace Implab.ServiceHost.Unity {
7 7
8 8 [XmlRoot("register", Namespace = Schema.ContainerConfigurationNamespace)]
9 public class RegisterElement : AbstractRegistration {
9 public class RegisterElement : TypeAbstractRegistration {
10 10
11 11 /// <summary>
12 12 /// An optional type which is registered as a service in the container, must be assignable to <see cref="ProvidesType">.
@@ -18,11 +18,19 namespace Implab.ServiceHost.Unity {
18 18 [XmlElement("constructor", typeof(ConstructorInjectionElement))]
19 19 [XmlElement("property", typeof(PropertyInjectionElement))]
20 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) {
24 context.Visit(this);
27 public override void Visit(TypeRegistrationBuilder builder) {
28 if(Injectors != null)
29 foreach(var injector in Injectors)
30 injector.Visit(builder);
25 31 }
32
33
26 34 }
27 35
28 36 } No newline at end of file
@@ -5,17 +5,39 using System.Linq;
5 5 using System.Xml.Serialization;
6 6 using Implab.Xml;
7 7 using Unity.Injection;
8 using Unity.Lifetime;
8 9 using Unity.Registration;
9 10
10 11 namespace Implab.ServiceHost.Unity {
12 /// <summary>
13 /// Базовый класс для формирования записей в контейнере, созволяет указать время жизни для записи
14 /// </summary>
11 15 public abstract class RegistrationBuilder {
12 16 public Type RegistrationType {
13 17 get;
14 18 private set;
15 19 }
16 20
21 internal LifetimeManager Lifetime { get; set; }
22
17 23 protected RegistrationBuilder(Type registrationType) {
18 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 43 } No newline at end of file
@@ -4,7 +4,7 using System.Xml.Serialization;
4 4
5 5 namespace Implab.ServiceHost.Unity
6 6 {
7 public class SerializedElement : AbstractRegistration, ISerializedValue {
7 public class SerializedElement : InstanceAbstractRegistration {
8 8 [XmlAttribute("href")]
9 9 public string Location { get; set; }
10 10
@@ -15,29 +15,15 namespace Implab.ServiceHost.Unity
15 15 [XmlAnyElement]
16 16 public XmlElement[] Content { get; set; }
17 17
18 string ISerializedValue.TypeName {
19 get {
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 }
18 public override void Visit(InstanceRegistrationBuilder builder) {
19 base.Visit(builder);
29 20
30 public XmlReader GetReader() {
31 if (!string.IsNullOrEmpty(Location))
32 return XmlReader.Create(Location);
33 if (Content != null && Content.Length > 0)
34 return Content[0].CreateNavigator().ReadSubtree();
35
36 throw new Exception("No content found, expected XML document");
37 }
38
39 public void Visit(InjectionValueBuilder builder) {
40 throw new NotImplementedException();
21 var parameter = new SerializedParameterElement {
22 TypeName = SerializedType,
23 Location = Location,
24 Content = Content
25 };
26 parameter.Visit(builder.ValueBuilder);
41 27 }
42 28 }
43 29 } No newline at end of file
@@ -5,7 +5,7 using System.Xml.Serialization;
5 5
6 6 namespace Implab.ServiceHost.Unity
7 7 {
8 public class SerializedParameterElement : InjectionParameterElement, ISerializedValue {
8 public class SerializedParameterElement : InjectionParameterElement {
9 9 [XmlAttribute("href")]
10 10 public string Location { get; set; }
11 11
@@ -22,7 +22,12 namespace Implab.ServiceHost.Unity
22 22 }
23 23
24 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 33 } No newline at end of file
@@ -1,10 +1,8
1 using Unity.Lifetime;
2
3 1 namespace Implab.ServiceHost.Unity
4 2 {
5 public class SimgletonLifetimeElement : LifetimeElement {
6 public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
7 return new SingletonLifetimeManager();
3 public class SingletonLifetimeElement : LifetimeElement {
4 public override void Visit(RegistrationBuilder builder) {
5 builder.Visit(this);
8 6 }
9 7 }
10 8 } No newline at end of file
@@ -17,10 +17,14 namespace Implab.ServiceHost.Unity {
17 17
18 18 CloseList,
19 19
20 OpenArray,
21
22 CloseArray,
23
20 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 29 TokenType m_token;
26 30
@@ -73,6 +77,12 namespace Implab.ServiceHost.Unity {
73 77 case ",":
74 78 m_token = TokenType.Comma;
75 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 88 return true;
@@ -82,7 +92,7 namespace Implab.ServiceHost.Unity {
82 92
83 93 public TypeReference Parse() {
84 94 var result = ReadTypeReference();
85 if (ReadToken())
95 if (Token != TokenType.Eof)
86 96 ThrowUnexpectedToken();
87 97 return result;
88 98 }
@@ -142,6 +152,10 namespace Implab.ServiceHost.Unity {
142 152 return typeReference;
143 153 }
144 154
155 int CountDimentions() {
156 return 0;
157 }
158
145 159 TypeReference[] ReadTypeReferenceList() {
146 160 var list = new List<TypeReference>();
147 161
@@ -11,7 +11,7 namespace Implab.ServiceHost.Unity {
11 11
12 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 16 public Type ImplementationType {
17 17 get;
@@ -5,11 +5,9 using System.Text;
5 5 using System.Text.RegularExpressions;
6 6 using Implab.Diagnostics;
7 7
8 namespace Implab.ServiceHost.Unity
9 {
8 namespace Implab.ServiceHost.Unity {
10 9 using static Trace<TypeResolver>;
11 public class TypeResolver
12 {
10 public class TypeResolver {
13 11 readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>();
14 12
15 13 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
@@ -49,7 +47,7 namespace Implab.ServiceHost.Unity
49 47 var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0;
50 48
51 49 Type resolved;
52 if(!m_cache.TryGetValue(reference.ToString(), out resolved)) {
50 if (!m_cache.TryGetValue(reference.ToString(), out resolved)) {
53 51 resolved = ResolveInternal(reference, args, argc);
54 52 if (resolved == null)
55 53 throw new Exception($"Failed to resolve {reference}");
@@ -65,7 +63,7 namespace Implab.ServiceHost.Unity
65 63
66 64 Type ResolveInternal(TypeReference reference, Type[] args, int argc) {
67 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 67 args,
70 68 argc,
71 69 reference.IsArray,
@@ -73,17 +71,24 namespace Implab.ServiceHost.Unity
73 71 );
74 72
75 73 if (resolved == null && m_parent != null)
76 resolved = m_parent.Resolve(reference);
77
74 resolved = m_parent.ResolveInternal(reference, args, argc);
75
78 76 return resolved;
79 77 }
80 78
81 79 public Type ProbeInNamespaces(string localName, Type[] args, int argc, bool isArray, string referenceName) {
82 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 83 var resolved = Probe(typeName);
86 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 92 Log("Probe succeed {0} in '{1}': {2} -> {3}", referenceName, ns, typeName, resolved.AssemblyQualifiedName);
88 93 return resolved;
89 94 } else {
@@ -97,7 +102,7 namespace Implab.ServiceHost.Unity
97 102 Type Probe(string typeName) {
98 103 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
99 104
100 foreach(var assembly in assemblies) {
105 foreach (var assembly in assemblies) {
101 106 var type = assembly.GetType(typeName);
102 107 if (type != null)
103 108 return type;
@@ -105,25 +110,16 namespace Implab.ServiceHost.Unity
105 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 114 var builder = new StringBuilder();
110
115
111 116 builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x))));
112 117 if (argc > 0) {
113 118 builder.Append('`');
114 119 builder.Append(argc);
115 120 }
116 121
117 if (args!= null && args.Length > 0) {
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();
122 return builder.ToString();
127 123 }
128 124 }
129 125 } No newline at end of file
@@ -1,7 +1,7
1 1 using System.Xml.Serialization;
2 2
3 3 namespace Implab.ServiceHost.Unity {
4 public class ValueElement : AbstractRegistration, ITextValue {
4 public class ValueElement : InstanceAbstractRegistration {
5 5
6 6 [XmlAttribute("value")]
7 7 public string Value { get; set; }
@@ -9,10 +9,8 namespace Implab.ServiceHost.Unity {
9 9 [XmlText]
10 10 public string Text { get; set; }
11 11
12 string ITextValue.Value {
13 get {
14 return string.IsNullOrEmpty(Value) ? Text : Value;
15 }
12 string GetTextValue() {
13 return string.IsNullOrEmpty(Value) ? Text : Value;
16 14 }
17 15
18 16 public string TypeName {
@@ -21,8 +19,13 namespace Implab.ServiceHost.Unity {
21 19 }
22 20 }
23 21
24 public override void Visit(ContainerBuilder context) {
25 context.Visit(this);
22 public override void Visit(InstanceRegistrationBuilder builder) {
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 31 } No newline at end of file
@@ -1,13 +1,21
1 using System.ComponentModel;
1 2 using System.Xml.Serialization;
2 3
3 4 namespace Implab.ServiceHost.Unity {
4 public class ValueParameterElement : InjectionParameterElement, ITextValue {
5 [XmlText]
5 public class ValueParameterElement : InjectionParameterElement {
6 6 [XmlAttribute("value")]
7 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 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 21 } No newline at end of file
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/readme.md to Implab.ServiceHost/docs/XmlConfiguration.md
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 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