##// END OF EJS Templates
Added tests for Implab.ServiceHost.Unity configuration loader.
cin -
r289:95896f882995 v3.0.14 v3
parent child
Show More
@@ -0,0 +1,29
1 <Project Sdk="Microsoft.NET.Sdk">
2 <PropertyGroup Condition="'$(OSTYPE)'=='linux'">
3 <TargetFrameworks>netcoreapp2.0;net46</TargetFrameworks>
4 <FrameworkPathOverride Condition="'$(TargetFramework)'=='net46'">/usr/lib/mono/4.5/</FrameworkPathOverride>
5 </PropertyGroup>
6
7 <PropertyGroup Condition="'$(OSTYPE)'=='windows'">
8 <TargetFrameworks>netcoreapp2.0;net46</TargetFrameworks>
9 </PropertyGroup>
10
11 <PropertyGroup>
12 <IsPackable>false</IsPackable>
13 </PropertyGroup>
14
15 <ItemGroup>
16 <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.6.0-preview-20180109-01" />
17 <PackageReference Include="System.Reactive" Version="4.0.0" />
18 <PackageReference Include="xunit" Version="2.3.1" />
19 <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
20 <ProjectReference Include="../Implab/Implab.csproj"/>
21 <ProjectReference Include="../Implab.ServiceHost/Implab.ServiceHost.csproj"/>
22 <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
23 </ItemGroup>
24
25 <ItemGroup>
26 <None Include="data/**/*.*" CopyToOutputDirectory="PreserveNewest" />
27 </ItemGroup>
28
29 </Project>
@@ -0,0 +1,74
1 <?xml version="1.0" encoding="UTF-8"?>
2 <container xmlns="http://implab.org/schemas/servicehost/unity.v1.xsd">
3 <namespace name="System"/>
4 <namespace name="System.Collections.Generic"/>
5 <namespace name="Implab.Components"/>
6 <namespace name="Implab.ServiceHost.Test.Mock"/>
7
8 <!-- Default FooService -->
9 <register type="FooService{}">
10 <property name="Name">
11 <value>I'm default!</value>
12 </property>
13 </register>
14
15 <!-- foo2 -->
16 <register name="foo2" type="Foo">
17 <property name="Name">
18 <value>GOOD</value>
19 </property>
20 <property name="IntValue">
21 <value>2</value>
22 </property>
23 </register>
24
25 <register type="Foo">
26 <method name="AddRange">
27 <array itemsType="Foo">
28 <dependency name="foo2"/>
29 </array>
30 </method>
31 </register>
32
33 <register type="IContainer{}" mapTo="Container{}">
34 <constructor/>
35 <method name="SetInstance">
36 <dependency type="T"/>
37 </method>
38 <method name="AddRange">
39 <array itemsType="T">
40 <dependency name="foo2-bar"/>
41 </array>
42 </method>
43 </register>
44
45 <register type="List{}">
46 <constructor />
47 </register>
48
49 <register type="IContainer{String}" mapTo="Container{String}">
50 <constructor/>
51 <method name="SetInstance">
52 <dependency type="String" name="name1"/>
53 </method>
54 </register>
55
56 <serialized type="Foo+Bar">
57 <Bar xmlns="" id="1">
58 <Name>Baaar</Name>
59 </Bar>
60 </serialized>
61
62 <value name="connection1" type="String"><![CDATA[Connect me <here>!]]></value>
63 <value name="name1" type="String" value="Hello!"/>
64
65 <factory name="foo3" type="IFactory{Foo}" mapTo="FooFactory">
66 <property name="Connection">
67 <value><![CDATA[Wired "" objecty <> name @#$%^&]]></value>
68 </property>
69 <property name="UseSsl">
70 <value>false</value>
71 </property>
72 </factory>
73
74 </container> No newline at end of file
@@ -0,0 +1,2
1 <container xmlns="http://implab.org/schemas/servicehost/unity.v1.xsd">
2 </container> No newline at end of file
@@ -0,0 +1,65
1 <?xml version="1.0"?>
2 <container xmlns="http://implab.org/schemas/servicehost/unity.v1.xsd">
3 <namespace name="System"/>
4 <namespace name="System.Collections.Generic"/>
5 <namespace name="Implab.Components"/>
6 <namespace name="Implab.ServiceHost.Test.Mock"/>
7
8 <register name="Big" type="Baz+Nut">
9 <property name="Size">
10 <value>5</value>
11 </property>
12 </register>
13 <register name="Mid" type="Baz+Nut">
14 <property name="Size">
15 <value>3</value>
16 </property>
17 </register>
18 <register name="Small" type="Baz+Nut">
19 <property name="Size">
20 <value>1</value>
21 </property>
22 </register>
23 <register type="Baz+Nut">
24 <property name="Size">
25 <value>2</value>
26 </property>
27 </register>
28
29 <!-- register a generic interface mapping to the generic type -->
30 <register type="IBox{}" mapTo="Box{}">
31 <property name="Value">
32 <!-- the dependency type is implied from the property and will be the generic parameter {T} -->
33 <dependency optional="true"/>
34 </property>
35 </register>
36
37 <factory name="Box2" type="BoxFactory{}">
38 </factory>
39
40 <register type="IBox{String}" mapTo="Box{String}">
41 <property name="Name">
42 <value>boxForString</value>
43 </property>
44 </register>
45
46 <register name="Small" type="IBox{}" mapTo="Box{}">
47 <property name="Value">
48 <dependency name="Small" optional="true"/>
49 </property>
50 </register>
51
52 <register type="SetOfBoxes{}">
53 <constructor/>
54 <method name="BoxValues">
55 <!-- only generic parameter or type without unresolved parameters
56 can be used, this is a limitation of Unity container. TODO -->
57 <array itemsType="T">
58 <default />
59 <dependency optional="true"/>
60 <dependency name="Small" optional="true"/>
61 </array>
62 </method>
63 </register>
64
65 </container> No newline at end of file
@@ -0,0 +1,6
1 <?xml version="1.0"?>
2 <Person xmlns="urn:implab:test:model">
3 <FirstName>Trohn</FirstName>
4 <LastName>Javolta</LastName>
5 <Age>88</Age>
6 </Person> No newline at end of file
@@ -0,0 +1,16
1 <?xml version="1.0"?>
2 <container xmlns="http://implab.org/schemas/servicehost/unity.v1.xsd">
3 <namespace name="System"/>
4 <namespace name="System.Collections.Generic"/>
5 <namespace name="Implab.Components"/>
6 <namespace name="Implab.ServiceHost.Test.Mock"/>
7
8 <serialized name="p1" type="Person">
9 <Person xmlns="urn:implab:test:model">
10 <FirstName>Com</FirstName>
11 <LastName>Truise</LastName>
12 <Age>99</Age>
13 </Person>
14 </serialized>
15 <serialized name="p2" type="Person" href="p2.xml"/>
16 </container> No newline at end of file
@@ -0,0 +1,63
1 <?xml version="1.0"?>
2 <container xmlns="http://implab.org/schemas/servicehost/unity.v1.xsd">
3 <namespace name="System"/>
4 <namespace name="System.Collections.Generic"/>
5 <namespace name="Implab.Components"/>
6 <namespace name="Implab.ServiceHost.Test.Mock"/>
7
8 <register name="Baz1" type="Baz">
9 <property name="Numbers">
10 <array>
11 <value>1</value>
12 <value>2</value>
13 <value>3</value>
14 </array>
15 </property>
16 </register>
17
18 <register type="Baz">
19 <property name="Nuts">
20 <array>
21 <dependency/>
22 <dependency name="Big"/>
23 <dependency name="Big"/>
24 <dependency name="Small"/>
25 <dependency name="Mid"/>
26 </array>
27 </property>
28 </register>
29
30 <register name="Big" type="Baz+Nut">
31 <property name="Size">
32 <value>5</value>
33 </property>
34 </register>
35 <register name="Mid" type="Baz+Nut">
36 <property name="Size">
37 <value>3</value>
38 </property>
39 </register>
40 <register name="Small" type="Baz+Nut">
41 <property name="Size">
42 <value>1</value>
43 </property>
44 </register>
45 <register type="Baz+Nut">
46 <property name="Size">
47 <value>2</value>
48 </property>
49 </register>
50 <factory type="BazFactory">
51 <provides name="Baz2" type="Baz"/>
52 </factory>
53
54 <factory name="Baz3" type="BazFactory">
55 <property name="IdGenerator">
56 <dependency/>
57 </property>
58 </factory>
59
60 <factory type="GuidFactory">
61 <singleton/>
62 </factory>
63 </container> No newline at end of file
@@ -0,0 +1,23
1 using System;
2 using System.Collections.Generic;
3
4 namespace Implab.ServiceHost.Test.Mock {
5 public class Baz {
6
7 public Guid Id {
8 get; set;
9 }
10
11 public int[] Numbers {
12 get; set;
13 }
14
15 public Nut[] Nuts {
16 get; set;
17 }
18
19 public class Nut {
20 public int Size { get; set; }
21 }
22 }
23 } No newline at end of file
@@ -0,0 +1,17
1 using System;
2 using Implab.Components;
3
4 namespace Implab.ServiceHost.Test.Mock {
5 public class BazFactory : IFactory<Baz> {
6
7 public Func<Guid> IdGenerator {
8 get; set;
9 }
10
11 Baz IFactory<Baz>.Create() {
12 return new Baz {
13 Id = IdGenerator?.Invoke() ?? Guid.Empty
14 };
15 }
16 }
17 } No newline at end of file
@@ -0,0 +1,13
1 using System;
2 using Implab.Components;
3
4 namespace Implab.ServiceHost.Test.Mock {
5 public class BoxFactory<T> : IFactory<IBox<T>> {
6 public IBox<T> Create() {
7 return new Box<T> {
8 Name = "Creepy sugar"
9 };
10 }
11 }
12
13 } No newline at end of file
@@ -0,0 +1,13
1 namespace Implab.ServiceHost.Test.Mock {
2 public class Box<T> : IBox<T> {
3
4 public string Name { get; set; }
5
6 public T Value { get; set; }
7
8 public T GetBoxValue() {
9 return Value;
10 }
11
12 }
13 } No newline at end of file
@@ -0,0 +1,10
1 using System;
2 using Implab.Components;
3
4 namespace Implab.ServiceHost.Test.Mock {
5 public class GuidFactory : IFactory<Guid> {
6 public Guid Create() {
7 return Guid.NewGuid();
8 }
9 }
10 } No newline at end of file
@@ -0,0 +1,6
1 namespace Implab.ServiceHost.Test.Mock {
2 public interface IBox<T> {
3 string Name { get; }
4 T GetBoxValue();
5 }
6 } No newline at end of file
@@ -0,0 +1,20
1 using System.Xml.Serialization;
2
3 namespace Implab.ServiceHost.Test.Mock
4 {
5 [XmlRoot(Namespace="urn:implab:test:model")]
6 public class Person {
7 public string FirstName { get; set; }
8
9 public string LastName { get; set; }
10
11 public int Age { get; set; }
12
13 [XmlIgnore]
14 public bool AgeSpecified { get; set; }
15
16
17 [XmlElement("Tag")]
18 public string[] Tags { get; set; }
19 }
20 } No newline at end of file
@@ -0,0 +1,21
1 using System;
2 using System.Linq;
3
4 namespace Implab.ServiceHost.Test.Mock {
5 public class SetOfBoxes<T> {
6
7 public Guid Uuid { get; set; }
8
9 public IBox<T>[] Boxes {
10 get; set;
11 }
12
13 public void BoxValues(T[] items) {
14 if (items == null || items.Length == 0)
15 return;
16
17 Boxes = items.Select(x => new Box<T> {Value = x}).ToArray();
18 }
19
20 }
21 } No newline at end of file
@@ -0,0 +1,94
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Linq;
5 using System.Threading;
6 using System.Threading.Tasks;
7 using Implab.Components;
8 using Implab.Diagnostics;
9 using Implab.ServiceHost.Test.Mock;
10 using Implab.ServiceHost.Unity;
11 using Unity;
12 using Xunit;
13
14 namespace Implab.Test {
15
16 public class UnityConfigTest {
17
18 [Fact]
19 public void CreateContainer() {
20 var container = new UnityContainer();
21
22 container.LoadXmlConfiguration(Path.Combine("data","container","empty.xml"));
23 }
24
25 [Fact]
26 public void SimpleServicesContainer() {
27 var container = new UnityContainer();
28
29 container.LoadXmlConfiguration(Path.Combine("data","container","simple.services.xml"));
30
31 // named service registration
32 var baz1 = container.Resolve<Baz>("Baz1");
33
34 Assert.Equal(new [] {1,2,3}, baz1.Numbers);
35
36 // default service registration
37 var baz = container.Resolve<Baz>();
38
39 Assert.Equal(new [] {2,5,5,1,3}, baz.Nuts.Select(x => x.Size));
40
41 // ServiceFactory registered without a name
42 // explicitly provides 'Baz2' service
43 var baz2 = container.Resolve<Baz>("Baz2");
44
45 // ServiceFactory registered with name 'Baz3'
46 // provides by default the service registration with same name
47 var baz3 = container.Resolve<Baz>("Baz3");
48
49 // This factory uses GuidGenerator registration
50 // to generate a new id value
51 Assert.NotEqual(Guid.Empty, baz3.Id);
52 }
53
54 [Fact]
55 public void GenericServicesContainer() {
56 var container = new UnityContainer();
57 container.LoadXmlConfiguration(Path.Combine("data","container","generic.services.xml"));
58
59 // resolve using a generig interface mapping
60 var box = container.Resolve<IBox<Baz.Nut>>();
61
62 Assert.NotNull(box.GetBoxValue());
63
64 // registered generic defines dependency of type {T}
65 // in this case it should resolve to the default Nut with Size=2
66 Assert.Equal(box.GetBoxValue().Size,2);
67
68 // generic factory which provides generic services
69 var box2 = container.Resolve<IBox<Baz.Nut>>();
70
71 var set1 = container.Resolve<SetOfBoxes<Baz.Nut>>();
72
73 Assert.Equal(new int?[] {null,2,1}, set1.Boxes?.Select(x => x.GetBoxValue()?.Size));
74 }
75
76 [Fact]
77 public void SerializedInstances() {
78 var container = new UnityContainer();
79 container.LoadXmlConfiguration(Path.Combine("data","container","serialized.instances.xml"));
80
81 var p1 = container.Resolve<Person>("p1");
82 var p2 = container.Resolve<Person>("p2");
83
84 Assert.Equal("Com", p1.FirstName);
85 Assert.True(p1.AgeSpecified);
86 Assert.Equal(99, p1.Age);
87
88 Assert.Equal("Javolta", p2.LastName);
89 Assert.True(p2.AgeSpecified);
90 Assert.Equal(88, p2.Age);
91 }
92
93 }
94 } No newline at end of file
@@ -1,27 +1,29
1 1 syntax: glob
2 2 Implab.Test/bin/
3 3 *.user
4 4 Implab.Test/obj/
5 5 *.userprefs
6 6 Implab/bin/
7 7 Implab/obj/
8 8 TestResults/
9 9 Implab.Fx/obj/
10 10 Implab.Fx/bin/
11 11 Implab.Fx.Test/bin/
12 12 Implab.Fx.Test/obj/
13 13 _ReSharper.Implab/
14 14 Implab.Diagnostics.Interactive/bin/
15 15 Implab.Diagnostics.Interactive/obj/
16 16 MonoPlay/bin/
17 17 MonoPlay/obj/
18 18 Implab.Test/Implab.Format.Test/bin/
19 19 Implab.Test/Implab.Format.Test/obj/
20 20 *.suo
21 21 Implab.Format.Test/bin/
22 22 Implab.Format.Test/obj/
23 23 packages/
24 24 Implab.Playground/obj/
25 25 Implab.Playground/bin/
26 26 Implab.ServiceHost/bin/
27 27 Implab.ServiceHost/obj/
28 Implab.ServiceHost.Test/bin/
29 Implab.ServiceHost.Test/obj/
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/AbstractContainerItem.cs to Implab.ServiceHost/src/Unity/AbstractContainerItem.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/AbstractInjectionParameter.cs to Implab.ServiceHost/src/Unity/AbstractInjectionParameter.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/AbstractMemberInjection.cs to Implab.ServiceHost/src/Unity/AbstractMemberInjection.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/AbstractRegistration.cs to Implab.ServiceHost/src/Unity/AbstractRegistration.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/ArrayParameterElement.cs to Implab.ServiceHost/src/Unity/ArrayParameterElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/ArrayTypeReference.cs to Implab.ServiceHost/src/Unity/ArrayTypeReference.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/AssemblyElement.cs to Implab.ServiceHost/src/Unity/AssemblyElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/ConstructorInjectionElement.cs to Implab.ServiceHost/src/Unity/ConstructorInjectionElement.cs
@@ -1,145 +1,156
1 1 using System;
2 2 using System.IO;
3 3 using System.Reflection;
4 4 using Implab.Diagnostics;
5 5 using Unity;
6 6
7 7 namespace Implab.ServiceHost.Unity {
8 8 using Log = Trace<ContainerBuilder>;
9 9
10 10 public class ContainerBuilder {
11 11
12 12 readonly TypeResolver m_resolver;
13 13
14 14 readonly IUnityContainer m_container;
15 15
16 16 readonly ContainerConfigurationSchema m_schema;
17 17
18 18 Uri m_location;
19 19
20 20 public IUnityContainer Container {
21 21 get {
22 22 return m_container;
23 23 }
24 24 }
25 25
26 26 public ContainerBuilder() : this(null, null) {
27 27 }
28 28
29 29 public ContainerBuilder(IUnityContainer container, ContainerConfigurationSchema schema) {
30 30 m_container = container ?? new UnityContainer();
31 31 m_resolver = new TypeResolver();
32 32 m_schema = schema ?? ContainerConfigurationSchema.Default;
33 33 }
34 34
35 35 public Type ResolveType(string typeReference) {
36 36 var resolved = string.IsNullOrEmpty(typeReference) ? null : m_resolver.Resolve(typeReference, true);
37 37 Log.Debug("ResolveType('{0}'): {1}", typeReference, resolved?.FullName);
38 38 return resolved;
39 39 }
40 40
41 41 public void Visit(ITypeRegistration registration) {
42 42 Safe.ArgumentNotNull(registration, nameof(registration));
43 43
44 44 var registrationType = registration.GetRegistrationType(this);
45 45 var implementationType = registration.GetImplementationType(this) ?? registrationType;
46 46
47 47 if (registrationType == null)
48 48 throw new Exception($"A type must be specified for the registration {registration.Name}");
49 49
50 50 var builder = new TypeRegistrationBuilder(
51 51 m_resolver,
52 52 registrationType,
53 implementationType
53 implementationType,
54 this
54 55 );
55 56
56 57 builder.Lifetime = registration.GetLifetime(this);
57 58
58 59 if (registration.MemberInjections != null) {
59 60 foreach(var member in registration.MemberInjections)
60 61 member.Visit(builder);
61 62 }
62 63
63 64 m_container.RegisterType(
64 65 builder.RegistrationType,
65 66 builder.ImplementationType,
66 67 registration.Name,
67 68 builder.Lifetime,
68 69 builder.Injections
69 70 );
70 71 }
71 72
72 73 public void Visit(IInstanceRegistration registration) {
73 74 Safe.ArgumentNotNull(registration, nameof(registration));
74 75
75 76 var registrationType = registration.GetRegistrationType(this);
76 77
77 78 var builder = new InstanceRegistrationBuilder (
78 79 m_resolver,
79 registrationType
80 registrationType,
81 this
80 82 );
81 83
82 84 builder.Lifetime = registration.GetLifetime(this);
83 85
84 86 if (registration.MemberInjections != null) {
85 87 foreach(var member in registration.MemberInjections)
86 88 member.Visit(builder.ValueBuilder);
87 89 }
88 90
89 91 if (builder.RegistrationType == null && builder.ValueBuilder.ValueType == null)
90 92 throw new Exception($"A type must be specified for the registration {registration.Name}");
91 93
92 94 m_container.RegisterInstance(
93 95 builder.RegistrationType ?? builder.ValueBuilder.ValueType,
94 96 registration.Name,
95 97 builder.ValueBuilder.Value,
96 98 builder.Lifetime
97 99 );
98 100 }
99 101
100 102 public void AddNamespace(string ns) {
101 103 m_resolver.AddNamespace(ns);
102 104 }
103 105
104 106 public void AddAssembly(string assembly) {
105 107
106 108 }
107 109
108 110 /// <summary>
109 111 /// Includes the confguration. Creates a new <see cref="ContainerBuilder"/>,
110 112 /// and loads the configuration to it. The created builder will share the
111 113 /// container and will have its own isolated type resolver.
112 114 /// </summary>
113 115 /// <param name="file">A path to configuration relative to the current configuration.</param>
114 116 public void Include(string file) {
115 117 var includeContext = new ContainerBuilder(m_container, m_schema);
116 118
117 119 if (m_location != null) {
118 120 var uri = new Uri(m_location, file);
119 121 includeContext.LoadConfig(uri);
120 122 } else {
121 123 includeContext.LoadConfig(file);
122 124 }
123 125 }
124 126
125 127 /// <summary>
128 /// Resolves a path ralatively to the current container configuration location.
129 /// </summary>
130 /// <param name="location">A path yto resolve</param>
131 /// <returns>Resolved Uri fot the specified location</returns>
132 public Uri MakeLocationUri(string location) {
133 return m_location != null ? new Uri(m_location, location) : new Uri(location);
134 }
135
136 /// <summary>
126 137 /// Loads a configuration from the specified local file.
127 138 /// </summary>
128 139 /// <param name="file">The path to the configuration file.</param>
129 140 public void LoadConfig(string file) {
130 141 Safe.ArgumentNotEmpty(file, nameof(file));
131 142
132 143 LoadConfig(new Uri(Path.GetFullPath(file)));
133 144 }
134 145
135 146 public void LoadConfig(Uri location) {
136 147 Safe.ArgumentNotNull(location, nameof(location));
137 148
138 149 m_location = location;
139 150
140 151 var config = m_schema.LoadConfig(location.ToString());
141 152 config.Visit(this);
142 153 }
143 154
144 155 }
145 156 } No newline at end of file
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/ContainerConfigurationSchema.cs to Implab.ServiceHost/src/Unity/ContainerConfigurationSchema.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/ContainerElement.cs to Implab.ServiceHost/src/Unity/ContainerElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/ContainerLifetimeElement.cs to Implab.ServiceHost/src/Unity/ContainerLifetimeElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/ContextLifetimeElement.cs to Implab.ServiceHost/src/Unity/ContextLifetimeElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/DefaultParameterElement.cs to Implab.ServiceHost/src/Unity/DefaultParameterElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/DependencyParameterElement.cs to Implab.ServiceHost/src/Unity/DependencyParameterElement.cs
@@ -1,63 +1,78
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Reflection;
4 4 using Implab.Components;
5 5 using Unity;
6 6 using Unity.Injection;
7 7 using Unity.Lifetime;
8 8
9 9 namespace Implab.ServiceHost.Unity {
10 10 public class FactoryActivator : ITypeRegistration {
11 11
12 12 class FactoryInjector : ITypeMemberInjection {
13 13 public InjectionFactory Factory { get; set; }
14 14 public void Visit(TypeRegistrationBuilder builder) {
15 15 builder.AddInjectionMember(Factory);
16 16 }
17 17 }
18 18
19 19
20 20 public Type FactoryType { get; set; }
21 21
22 22 public string FactoryName { get; set; }
23 23
24 24 public Type RegistrationType { get; set; }
25 25
26 26 public LifetimeManager Lifetime { get; set; }
27 27
28 28 public IEnumerable<ITypeMemberInjection> MemberInjections {
29 29 get {
30 yield return new FactoryInjector {
31 Factory = (InjectionFactory)GetType()
32 .GetMethod(nameof(CreateInjectionFactory), BindingFlags.Static | BindingFlags.NonPublic)
33 .MakeGenericMethod(FactoryType, RegistrationType)
34 .Invoke(null, new [] { FactoryName })
35 };
30 if (RegistrationType == null)
31 throw new Exception($"RegistrationType must be specified");
32 if (!typeof(IFactory<>).MakeGenericType(RegistrationType).IsAssignableFrom(FactoryType))
33 throw new Exception($"The factory {FactoryType} can't be used to create {RegistrationType} instances");
34
35 if (FactoryType.ContainsGenericParameters) {
36 yield return new FactoryInjector {
37 Factory = CreateDynamicInjectionFactory(FactoryName)
38 };
39 } else {
40 yield return new FactoryInjector {
41 Factory = (InjectionFactory)GetType()
42 .GetMethod(nameof(CreateInjectionFactory), BindingFlags.Static | BindingFlags.NonPublic)
43 .MakeGenericMethod(FactoryType, RegistrationType)
44 .Invoke(null, new [] { FactoryName })
45 };
46 }
36 47 }
37 48 }
38 49
39 50 public string Name { get; set; }
40 51
41 52 public Type GetRegistrationType(ContainerBuilder builder) {
42 53 return RegistrationType;
43 54 }
44 55
45 56 public LifetimeManager GetLifetime(ContainerBuilder builder) {
46 57 return Lifetime;
47 58 }
48 59
49 60 public Type GetImplementationType(ContainerBuilder builder) {
50 61 return null;
51 62 }
52 63
53 64 /// <summary>
54 65 /// Указывает зависимость, реализующую интерфейс <see cref="IFactory{TObj}"/>,
55 66 /// которая будет использоваться в качестве фабрики для создания объектов
56 67 /// </summary>
57 68 /// <param name="dependencyName"></param>
58 69 static InjectionFactory CreateInjectionFactory<TFac, TObj>(string dependencyName) where TFac : IFactory<TObj> {
59 70
60 71 return new InjectionFactory(c => c.Resolve<TFac>(dependencyName).Create());
61 72 }
73
74 static InjectionFactory CreateDynamicInjectionFactory(string dependencyName) {
75 return new InjectionFactory((c,t,name) => ((IFactory<object>)c.Resolve(t, dependencyName)).Create());
76 }
62 77 }
63 78 } No newline at end of file
@@ -1,73 +1,73
1 1 using System;
2 2 using System.Xml.Serialization;
3 3 using Implab.Components;
4 4
5 5 namespace Implab.ServiceHost.Unity {
6 6 /// <summary>
7 7 /// Расширяет стандартную регистрацию типа до фабрики, вместе с регистрацией
8 8 /// самой фабрики создаются регистрации сервисов, которые она предоставляет.
9 9 /// </summary>
10 10 public class FactoryElement : RegisterElement, ITypeRegistration {
11 11
12 12 /// <summary>
13 13 /// Записи о сервисах, которые создаются данной фабрикой.
14 14 /// </summary>
15 15 /// <remarks>
16 16 /// Сервисы, которые указаны в регистарциях они должны соответсвовать тому,
17 17 /// что фабрика возвращает, но это остается на откуп контейнера
18 18 /// </remarks>
19 19 [XmlElement("provides")]
20 20 public ProvidesElement[] Provides { get; set; }
21 21
22 22 /// <summary>
23 23 /// Переопределяет стандарное поведение регистрации типа в контейнере,
24 24 /// дополняя его регистрацией фабричных методов для получения типов.
25 25 /// </summary>
26 26 /// <param name="builder">Объект для конфигурирования контейнера.</param>
27 27 public override void Visit(ContainerBuilder builder) {
28 28 var factoryType = GetRegistrationType(builder.ResolveType);
29 29
30 30 base.Visit(builder);
31 31
32 32 if (Provides != null && Provides.Length > 0) {
33 33 // если регистрации явно заданы, используеися информация из них
34 34 foreach(var item in Provides) {
35 35 var activator = new FactoryActivator {
36 36 Name = item.RegistrationName,
37 37 RegistrationType = builder.ResolveType(item.RegistrationType),
38 38 FactoryName = Name,
39 39 FactoryType = factoryType,
40 Lifetime = item.Lifetime.GetLifetime(builder)
40 Lifetime = item.Lifetime?.GetLifetime(builder)
41 41 };
42 42 builder.Visit(activator);
43 43 }
44 44 } else {
45 45 // если регистрация явно не задана, в качестве сервиса для регистрации
46 46 // используется тип создаваемый фабрикой, который будет добавлен в контейнер
47 47 // с темже именем, что и сама фабрика (разные типы могут иметь одно имя для регистрации)
48 48 var providedType = (
49 49 factoryType.IsGenericType && factoryType.GetGenericTypeDefinition() == typeof(IFactory<>) ?
50 50 factoryType :
51 51 factoryType.GetInterface(typeof(IFactory<>).FullName)
52 52 )?
53 53 .GetGenericArguments()[0];
54 54
55 55 // не удалось определеить тип
56 56 if (providedType == null)
57 57 throw new ArgumentException("Failed to determine a type provided by the factory");
58 58
59 59 if (providedType.IsGenericParameter)
60 60 throw new ArgumentException("Can't register a generic type paramter as a service");
61 61
62 62 var activator = new FactoryActivator {
63 63 Name = Name,
64 64 RegistrationType = providedType,
65 65 FactoryName = Name,
66 66 FactoryType = factoryType
67 67 };
68 68
69 69 builder.Visit(activator);
70 70 }
71 71 }
72 72 }
73 73 } No newline at end of file
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/HierarchicalLifetimeElement.cs to Implab.ServiceHost/src/Unity/HierarchicalLifetimeElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/IInjectionParameter.cs to Implab.ServiceHost/src/Unity/IInjectionParameter.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/IInstanceRegistration.cs to Implab.ServiceHost/src/Unity/IInstanceRegistration.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/IRegistration.cs to Implab.ServiceHost/src/Unity/IRegistration.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/ITypeMemberInjection.cs to Implab.ServiceHost/src/Unity/ITypeMemberInjection.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/ITypeRegistration.cs to Implab.ServiceHost/src/Unity/ITypeRegistration.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/IncludeElement.cs to Implab.ServiceHost/src/Unity/IncludeElement.cs
@@ -1,137 +1,142
1 1 using System;
2 2 using System.Collections;
3 3 using System.Collections.Generic;
4 4 using System.ComponentModel;
5 5 using System.Linq;
6 6 using System.Xml.Serialization;
7 7 using Unity.Injection;
8 8
9 9 namespace Implab.ServiceHost.Unity {
10 10
11 11 public class InjectionParameterBuilder {
12 12
13 13 readonly TypeResolver m_resolver;
14 14
15 15 public Type DefaultType { get; private set; }
16 16
17 17 public Type ValueType { get; private set; }
18 18
19 public ContainerBuilder Root { get; private set; }
20
19 21 object m_value;
20 22
21 23 public object Value {
22 24 get {
23 25 if (!ValueSpecified)
24 26 throw new InvalidOperationException("The regular value must be set (dependency or array are not situable in this context)");
25 27 return m_value;
26 28 }
27 29 }
28 30
29 31 public bool ValueSpecified { get; private set; }
30 32
31 33 InjectionParameterValue m_injection;
32 34
33 35 public InjectionParameterValue Injection {
34 36 get {
35 37 if (m_injection == null)
36 38 throw new InvalidOperationException("The injection parameter is not specified");
37 39 return m_injection;
38 40 }
39 41 }
40 42
41 43 public bool InjectionSpecified {
42 44 get { return m_injection != null; }
43 45 }
44 46
45 internal InjectionParameterBuilder(TypeResolver resolver, Type defaultType) {
47 internal InjectionParameterBuilder(TypeResolver resolver, Type defaultType, ContainerBuilder root) {
46 48 m_resolver = resolver;
47 49 DefaultType = defaultType;
50 Root = root;
48 51 }
49 52
50 53 public Type ResolveInjectedValueType(string typeSpec) {
51 54 if (string.IsNullOrEmpty(typeSpec)) {
52 55 if (DefaultType == null)
53 56 throw new Exception("The type must be specified");
54 57 return DefaultType;
55 58 }
56 59 return m_resolver.Resolve(typeSpec, true);
57 60 }
58 61
59 62 public Type ResolveType(string typeSpec) {
60 63 return string.IsNullOrEmpty(typeSpec) ? null : m_resolver.Resolve(typeSpec, true);
61 64 }
62 65
63 66 public void SetValue(Type type, object value) {
64 67 Safe.ArgumentNotNull(type, nameof(type));
65 68
66 69 ValueType = type;
67 70 m_value = value;
68 71 ValueSpecified = true;
69 72
70 73 m_injection = new InjectionParameter(type, value);
71 74 }
72 75
73 76 public void SetDependency(Type type, string name, bool optional) {
74 77 Safe.ArgumentNotNull(type, nameof(type));
75 78
76 79 ValueType = type;
77 80 ValueSpecified = false;
78 81 m_value = null;
79 82
80 m_injection = optional ? (InjectionParameterValue)new OptionalParameter(type, name) : new ResolvedParameter(type, name);
83 m_injection = optional ?
84 type.IsGenericParameter ?
85 new OptionalGenericParameter(type.Name, name)
86 : (InjectionParameterValue)new OptionalParameter(type, name)
87 : new ResolvedParameter(type, name);
81 88 }
82 89
83 90 internal void Visit(ArrayParameterElement arrayParameter) {
84 91 Type itemsType = null;
85 92 var arrayType = string.IsNullOrEmpty(arrayParameter.TypeName) ? null : ResolveType(arrayParameter.TypeName);
86 93
87 94 if (arrayType == null)
88 95 arrayType = DefaultType;
89 96
90 97
91 98 if (!string.IsNullOrEmpty(arrayParameter.ItemsType)) {
92 99 itemsType = ResolveType(arrayParameter.ItemsType);
93 100 arrayType = itemsType.MakeArrayType();
94 101 } else {
95 102 itemsType = GetItemsType(arrayType);
96 103 }
97 104
98 105 if (itemsType == null)
99 106 throw new Exception("Failed to determine array elements type");
100 107
101 108 InjectionParameterValue[] injections = (arrayParameter.Items ?? new AbstractInjectionParameter[0])
102 109 .Select(x => {
103 var builder = new InjectionParameterBuilder(m_resolver, itemsType);
110 var builder = new InjectionParameterBuilder(m_resolver, itemsType, Root);
104 111 x.Visit(builder);
105 112 return builder.Injection;
106 113 })
107 114 .ToArray();
108 115
109 var array = itemsType.IsGenericParameter ?
116 m_injection = itemsType.IsGenericParameter ?
110 117 (InjectionParameterValue)new GenericResolvedArrayParameter(itemsType.Name, injections) :
111 118 new ResolvedArrayParameter(itemsType, injections);
112 119
113 120 ValueType = arrayType;
114 121 m_value = null;
115 122 ValueSpecified = false;
116
117 m_injection = array;
118 123 }
119 124
120 125 Type GetItemsType(Type collectionType) {
121 126 if (collectionType == null)
122 127 return null;
123 128
124 129 Type itemsType = null;
125 130
126 if (collectionType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) {
131 if (collectionType.IsGenericType && collectionType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) {
127 132 itemsType = collectionType.GetGenericArguments()[0];
128 133 } else if (collectionType == typeof(IEnumerable)) {
129 134 itemsType = typeof(object);
130 135 } else {
131 136 itemsType = collectionType.GetInterface(typeof(IEnumerable<>).FullName)?.GetGenericArguments()[0];
132 137 }
133 138
134 139 return itemsType;
135 140 }
136 141 }
137 142 } No newline at end of file
@@ -1,13 +1,13
1 1 using System;
2 2
3 3 namespace Implab.ServiceHost.Unity
4 4 {
5 5 public class InstanceRegistrationBuilder : RegistrationBuilder {
6 6
7 7 public InjectionParameterBuilder ValueBuilder { get; private set; }
8 8
9 internal InstanceRegistrationBuilder(TypeResolver typeResolver, Type registrationType) : base(registrationType) {
10 ValueBuilder = new InjectionParameterBuilder(typeResolver, registrationType);
9 internal InstanceRegistrationBuilder(TypeResolver typeResolver, Type registrationType, ContainerBuilder root) : base(registrationType, root) {
10 ValueBuilder = new InjectionParameterBuilder(typeResolver, registrationType, root);
11 11 }
12 12 }
13 13 } No newline at end of file
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/LifetimeElement.cs to Implab.ServiceHost/src/Unity/LifetimeElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/MethodInjectionElement.cs to Implab.ServiceHost/src/Unity/MethodInjectionElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/NamespaceElement.cs to Implab.ServiceHost/src/Unity/NamespaceElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/NestedTypeReference.cs to Implab.ServiceHost/src/Unity/NestedTypeReference.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/PropertyInjectionElement.cs to Implab.ServiceHost/src/Unity/PropertyInjectionElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/ProvidesElement.cs to Implab.ServiceHost/src/Unity/ProvidesElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/RegisterElement.cs to Implab.ServiceHost/src/Unity/RegisterElement.cs
@@ -1,27 +1,32
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.ComponentModel;
4 4 using System.Linq;
5 5 using System.Xml.Serialization;
6 6 using Implab.Xml;
7 7 using Unity.Injection;
8 8 using Unity.Lifetime;
9 9 using Unity.Registration;
10 10
11 11 namespace Implab.ServiceHost.Unity {
12 12 /// <summary>
13 13 /// Базовый класс для формирования записей в контейнере, созволяет указать время жизни для записи
14 14 /// </summary>
15 15 public abstract class RegistrationBuilder {
16 public ContainerBuilder Root {
17 get; private set;
18 }
19
16 20 public Type RegistrationType {
17 21 get;
18 22 private set;
19 23 }
20 24
21 25 internal LifetimeManager Lifetime { get; set; }
22 26
23 protected RegistrationBuilder(Type registrationType) {
27 protected RegistrationBuilder(Type registrationType, ContainerBuilder root) {
28 Root = root;
24 29 RegistrationType = registrationType;
25 30 }
26 31 }
27 32 } No newline at end of file
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/RootTypeReference.cs to Implab.ServiceHost/src/Unity/RootTypeReference.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/Schema.cs to Implab.ServiceHost/src/Unity/Schema.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/SerializedElement.cs to Implab.ServiceHost/src/Unity/SerializedElement.cs
@@ -1,33 +1,33
1 1 using System;
2 2 using System.Xml;
3 3 using System.Xml.Schema;
4 4 using System.Xml.Serialization;
5 5
6 6 namespace Implab.ServiceHost.Unity
7 7 {
8 8 public class SerializedParameterElement : AbstractInjectionParameter {
9 9 [XmlAttribute("href")]
10 10 public string Location { get; set; }
11 11
12 12 [XmlAnyElement]
13 13 public XmlElement[] Content { get; set; }
14 14
15 public XmlReader GetReader() {
15 public XmlReader GetReader(InjectionParameterBuilder builder) {
16 16 if (!string.IsNullOrEmpty(Location))
17 return XmlReader.Create(Location);
17 return XmlReader.Create(builder.Root.MakeLocationUri(Location).ToString());
18 18 if (Content != null && Content.Length > 0)
19 19 return Content[0].CreateNavigator().ReadSubtree();
20 20
21 21 throw new Exception("No content found, expected XML document");
22 22 }
23 23
24 24 public override void Visit(InjectionParameterBuilder builder) {
25 25 var type = builder.ResolveInjectedValueType(TypeName);
26 26
27 27 var serializer = new XmlSerializer(type);
28 using(var reader = GetReader())
28 using(var reader = GetReader(builder))
29 29 builder.SetValue(type, serializer.Deserialize(reader));
30 30
31 31 }
32 32 }
33 33 } No newline at end of file
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/SingletonLifetimeElement.cs to Implab.ServiceHost/src/Unity/SingletonLifetimeElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/SpecializedTypeReference.cs to Implab.ServiceHost/src/Unity/SpecializedTypeReference.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/TypeReference.cs to Implab.ServiceHost/src/Unity/TypeReference.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/TypeReferenceParser.cs to Implab.ServiceHost/src/Unity/TypeReferenceParser.cs
@@ -1,81 +1,81
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using Unity.Injection;
5 5 using Unity.Registration;
6 6
7 7 namespace Implab.ServiceHost.Unity {
8 8 public class TypeRegistrationBuilder : RegistrationBuilder {
9 9
10 10 readonly TypeResolver m_resolver;
11 11
12 12 readonly List<InjectionMember> m_injections = new List<InjectionMember>();
13 13
14 14 internal InjectionMember[] Injections { get { return m_injections.ToArray(); } }
15 15
16 16 public Type ImplementationType {
17 17 get;
18 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, ContainerBuilder root) : base(registrationType, root) {
22 22 ImplementationType = implementationType;
23 23
24 24 // when registering a generic mapping, register all generic parameter names as local types
25 25 if (ImplementationType.IsGenericTypeDefinition) {
26 26 m_resolver = new TypeResolver(resolver);
27 27
28 28 foreach (var p in ImplementationType.GetGenericArguments())
29 29 m_resolver.AddMapping(p.Name, p);
30 30 } else {
31 31 m_resolver = resolver;
32 32 }
33 33 }
34 34
35 35 internal void Visit(ConstructorInjectionElement constructorInjection) {
36 36
37 37
38 38 var parameters = constructorInjection.Parameters?
39 39 .Select(x => {
40 var valueBuilder = new InjectionParameterBuilder(m_resolver, null);
40 var valueBuilder = new InjectionParameterBuilder(m_resolver, null, Root);
41 41 x.Visit(valueBuilder);
42 42 return valueBuilder.Injection;
43 43 })
44 44 .ToArray();
45 45
46 46 var injection = parameters != null ? new InjectionConstructor(parameters) : new InjectionConstructor();
47 47 m_injections.Add(injection);
48 48 }
49 49
50 50 internal void Visit(MethodInjectionElement methodInjection) {
51 51 var parameters = methodInjection.Parameters?
52 52 .Select(x => {
53 var valueBuilder = new InjectionParameterBuilder(m_resolver, null);
53 var valueBuilder = new InjectionParameterBuilder(m_resolver, null, Root);
54 54 x.Visit(valueBuilder);
55 55 return valueBuilder.Injection;
56 56 })
57 57 .ToArray();
58 58
59 59 var injection = parameters != null ? new InjectionMethod(methodInjection.Name, parameters) : new InjectionMethod(methodInjection.Name);
60 60 m_injections.Add(injection);
61 61 }
62 62
63 63 internal void Visit(PropertyInjectionElement propertyInjection) {
64 64 if (propertyInjection.Value == null)
65 65 throw new Exception($"A value value must be specified for the property '{propertyInjection.Name}'");
66 66
67 67 var propertyType = ImplementationType.GetProperty(propertyInjection.Name)?.PropertyType;
68 var valueContext = new InjectionParameterBuilder(m_resolver, propertyType);
68 var valueContext = new InjectionParameterBuilder(m_resolver, propertyType, Root);
69 69
70 70 propertyInjection.Value.Visit(valueContext);
71 71 var injection = new InjectionProperty(propertyInjection.Name, valueContext.Injection);
72 72 m_injections.Add(injection);
73 73 }
74 74
75 75 public void AddInjectionMember(InjectionMember injection) {
76 76 Safe.ArgumentNotNull(injection, nameof(injection));
77 77
78 78 m_injections.Add(injection);
79 79 }
80 80 }
81 81 } No newline at end of file
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/TypeResolutionContext.cs to Implab.ServiceHost/src/Unity/TypeResolutionContext.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/TypeResolver.cs to Implab.ServiceHost/src/Unity/TypeResolver.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/UnityContainerExtensions.cs to Implab.ServiceHost/src/Unity/UnityContainerExtensions.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/ValueElement.cs to Implab.ServiceHost/src/Unity/ValueElement.cs
1 NO CONTENT: file renamed from Implab.ServiceHost/Unity/ValueParameterElement.cs to Implab.ServiceHost/src/Unity/ValueParameterElement.cs
1 NO CONTENT: file renamed from Implab.Test/DiagnosticsTest.cs to Implab.Test/src/DiagnosticsTest.cs
1 NO CONTENT: file renamed from Implab.Test/JsonTests.cs to Implab.Test/src/JsonTests.cs
1 NO CONTENT: file renamed from Implab.Test/MockPollComponent.cs to Implab.Test/src/MockPollComponent.cs
1 NO CONTENT: file renamed from Implab.Test/Model/Person.cs to Implab.Test/src/Model/Person.cs
1 NO CONTENT: file renamed from Implab.Test/PromiseHelper.cs to Implab.Test/src/PromiseHelper.cs
1 NO CONTENT: file renamed from Implab.Test/RunnableComponentTests.cs to Implab.Test/src/RunnableComponentTests.cs
@@ -1,55 +1,69
1 1
2 2 Microsoft Visual Studio Solution File, Format Version 12.00
3 3 # Visual Studio 15
4 4 VisualStudioVersion = 15.0.27428.2005
5 5 MinimumVisualStudioVersion = 10.0.40219.1
6 6 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Implab", "Implab\Implab.csproj", "{FF2052B6-9C8F-4022-A347-F07ABF635885}"
7 7 EndProject
8 8 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Implab.Test", "Implab.Test\Implab.Test.csproj", "{6CD0DA18-8D9B-4AA8-A3DC-17322E27335E}"
9 9 EndProject
10 10 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Playground", "Implab.Playground\Implab.Playground.csproj", "{100DFEB0-75BE-436F-ADDF-1F46EF433F46}"
11 11 EndProject
12 12 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.ServiceHost", "Implab.ServiceHost\Implab.ServiceHost.csproj", "{8B79FCBE-50DD-40A0-9B5E-E572072E4868}"
13 13 EndProject
14 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.ServiceHost.Test", "Implab.ServiceHost.Test\Implab.ServiceHost.Test.csproj", "{CB844F94-E555-4F25-A932-7CB85C98CF86}"
15 EndProject
14 16 Global
15 17 GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 18 Debug|Any CPU = Debug|Any CPU
17 19 Release|Any CPU = Release|Any CPU
18 20 Debug|x64 = Debug|x64
19 21 Debug|x86 = Debug|x86
20 22 Release|x64 = Release|x64
21 23 Release|x86 = Release|x86
22 24 EndGlobalSection
23 25 GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 26 {FF2052B6-9C8F-4022-A347-F07ABF635885}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 27 {FF2052B6-9C8F-4022-A347-F07ABF635885}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 28 {FF2052B6-9C8F-4022-A347-F07ABF635885}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 29 {FF2052B6-9C8F-4022-A347-F07ABF635885}.Release|Any CPU.Build.0 = Release|Any CPU
28 30 {6CD0DA18-8D9B-4AA8-A3DC-17322E27335E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 31 {6CD0DA18-8D9B-4AA8-A3DC-17322E27335E}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 32 {6CD0DA18-8D9B-4AA8-A3DC-17322E27335E}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 33 {6CD0DA18-8D9B-4AA8-A3DC-17322E27335E}.Release|Any CPU.Build.0 = Release|Any CPU
32 34 {100DFEB0-75BE-436F-ADDF-1F46EF433F46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 35 {100DFEB0-75BE-436F-ADDF-1F46EF433F46}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 36 {100DFEB0-75BE-436F-ADDF-1F46EF433F46}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 37 {100DFEB0-75BE-436F-ADDF-1F46EF433F46}.Release|Any CPU.Build.0 = Release|Any CPU
36 38 {8B79FCBE-50DD-40A0-9B5E-E572072E4868}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 39 {8B79FCBE-50DD-40A0-9B5E-E572072E4868}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 40 {8B79FCBE-50DD-40A0-9B5E-E572072E4868}.Debug|x64.ActiveCfg = Debug|x64
39 41 {8B79FCBE-50DD-40A0-9B5E-E572072E4868}.Debug|x64.Build.0 = Debug|x64
40 42 {8B79FCBE-50DD-40A0-9B5E-E572072E4868}.Debug|x86.ActiveCfg = Debug|x86
41 43 {8B79FCBE-50DD-40A0-9B5E-E572072E4868}.Debug|x86.Build.0 = Debug|x86
42 44 {8B79FCBE-50DD-40A0-9B5E-E572072E4868}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 45 {8B79FCBE-50DD-40A0-9B5E-E572072E4868}.Release|Any CPU.Build.0 = Release|Any CPU
44 46 {8B79FCBE-50DD-40A0-9B5E-E572072E4868}.Release|x64.ActiveCfg = Release|x64
45 47 {8B79FCBE-50DD-40A0-9B5E-E572072E4868}.Release|x64.Build.0 = Release|x64
46 48 {8B79FCBE-50DD-40A0-9B5E-E572072E4868}.Release|x86.ActiveCfg = Release|x86
47 49 {8B79FCBE-50DD-40A0-9B5E-E572072E4868}.Release|x86.Build.0 = Release|x86
50 {CB844F94-E555-4F25-A932-7CB85C98CF86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51 {CB844F94-E555-4F25-A932-7CB85C98CF86}.Debug|Any CPU.Build.0 = Debug|Any CPU
52 {CB844F94-E555-4F25-A932-7CB85C98CF86}.Debug|x64.ActiveCfg = Debug|x64
53 {CB844F94-E555-4F25-A932-7CB85C98CF86}.Debug|x64.Build.0 = Debug|x64
54 {CB844F94-E555-4F25-A932-7CB85C98CF86}.Debug|x86.ActiveCfg = Debug|x86
55 {CB844F94-E555-4F25-A932-7CB85C98CF86}.Debug|x86.Build.0 = Debug|x86
56 {CB844F94-E555-4F25-A932-7CB85C98CF86}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 {CB844F94-E555-4F25-A932-7CB85C98CF86}.Release|Any CPU.Build.0 = Release|Any CPU
58 {CB844F94-E555-4F25-A932-7CB85C98CF86}.Release|x64.ActiveCfg = Release|x64
59 {CB844F94-E555-4F25-A932-7CB85C98CF86}.Release|x64.Build.0 = Release|x64
60 {CB844F94-E555-4F25-A932-7CB85C98CF86}.Release|x86.ActiveCfg = Release|x86
61 {CB844F94-E555-4F25-A932-7CB85C98CF86}.Release|x86.Build.0 = Release|x86
48 62 EndGlobalSection
49 63 GlobalSection(SolutionProperties) = preSolution
50 64 HideSolutionNode = FALSE
51 65 EndGlobalSection
52 66 GlobalSection(ExtensibilityGlobals) = postSolution
53 67 SolutionGuid = {36D837FC-4CDD-4AEA-87BF-F130FEB22E02}
54 68 EndGlobalSection
55 69 EndGlobal
@@ -1,26 +1,26
1 1 <Project Sdk="Microsoft.NET.Sdk">
2 2
3 3 <PropertyGroup>
4 4 <Authors>Sergey Smirnov</Authors>
5 5 <Title>Implab library</Title>
6 6 <Description>Provides some helper clesses like XML serialization helpers, JSON XML reader,
7 7 JSON pull-parser, ECMA-style promises, lightweight synchonization routines Signal
8 8 and SharedLock, Trace helpers on top of System.Diagnostics, ObjectPool etc.
9 9 </Description>
10 10 <Copyright>2012-2018 Sergey Smirnov</Copyright>
11 11 <Version>3.0.14</Version>
12 12 <PackageLicenseUrl>https://hg.implab.org/pub/ImplabNet/file/tip/Implab/license.txt</PackageLicenseUrl>
13 13 <PackageProjectUrl>https://implab.org</PackageProjectUrl>
14 14 <RepositoryUrl>https://hg.implab.org/pub/ImplabNet/</RepositoryUrl>
15 15 <RepositoryType>mercurial</RepositoryType>
16 16 <PackageTags>IMPLAB;Json pull-parser;Json Xml;async;diagnostics;serialization;</PackageTags>
17 17 <TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
18 18 <FrameworkPathOverride Condition="'$(TargetFramework)'=='net46' and '$(OSTYPE)'=='linux'">/usr/lib/mono/4.5/</FrameworkPathOverride>
19 19 <DefineConstants Condition="'$(TargetFramework)'=='net46'">NETFX_TRACE_BUG;$(DefineConstants)</DefineConstants>
20 20 </PropertyGroup>
21 21
22 22 <ItemGroup>
23 <EmbeddedResource Include="Xml\json.xsl"/>
23 <EmbeddedResource Include="src\Xml\json.xsl"/>
24 24 </ItemGroup>
25 25
26 26 </Project>
1 NO CONTENT: file renamed from Implab/AbstractEvent.cs to Implab/src/AbstractEvent.cs
1 NO CONTENT: file renamed from Implab/Automaton/AutomatonConst.cs to Implab/src/Automaton/AutomatonConst.cs
1 NO CONTENT: file renamed from Implab/Automaton/AutomatonTransition.cs to Implab/src/Automaton/AutomatonTransition.cs
1 NO CONTENT: file renamed from Implab/Automaton/DFATable.cs to Implab/src/Automaton/DFATable.cs
1 NO CONTENT: file renamed from Implab/Automaton/IAlphabet.cs to Implab/src/Automaton/IAlphabet.cs
1 NO CONTENT: file renamed from Implab/Automaton/IAlphabetBuilder.cs to Implab/src/Automaton/IAlphabetBuilder.cs
1 NO CONTENT: file renamed from Implab/Automaton/IDFATable.cs to Implab/src/Automaton/IDFATable.cs
1 NO CONTENT: file renamed from Implab/Automaton/IDFATableBuilder.cs to Implab/src/Automaton/IDFATableBuilder.cs
1 NO CONTENT: file renamed from Implab/Automaton/IndexedAlphabetBase.cs to Implab/src/Automaton/IndexedAlphabetBase.cs
1 NO CONTENT: file renamed from Implab/Automaton/MapAlphabet.cs to Implab/src/Automaton/MapAlphabet.cs
1 NO CONTENT: file renamed from Implab/Automaton/ParserException.cs to Implab/src/Automaton/ParserException.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/AltToken.cs to Implab/src/Automaton/RegularExpressions/AltToken.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/BinaryToken.cs to Implab/src/Automaton/RegularExpressions/BinaryToken.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/CatToken.cs to Implab/src/Automaton/RegularExpressions/CatToken.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/EmptyToken.cs to Implab/src/Automaton/RegularExpressions/EmptyToken.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/EndToken.cs to Implab/src/Automaton/RegularExpressions/EndToken.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/EndTokenT.cs to Implab/src/Automaton/RegularExpressions/EndTokenT.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/ITaggedDFABuilder.cs to Implab/src/Automaton/RegularExpressions/ITaggedDFABuilder.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/IVisitor.cs to Implab/src/Automaton/RegularExpressions/IVisitor.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/RegularDFA.cs to Implab/src/Automaton/RegularExpressions/RegularDFA.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/RegularExpressionVisitor.cs to Implab/src/Automaton/RegularExpressions/RegularExpressionVisitor.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/RegularExpressionVisitorT.cs to Implab/src/Automaton/RegularExpressions/RegularExpressionVisitorT.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/StarToken.cs to Implab/src/Automaton/RegularExpressions/StarToken.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/SymbolToken.cs to Implab/src/Automaton/RegularExpressions/SymbolToken.cs
1 NO CONTENT: file renamed from Implab/Automaton/RegularExpressions/Token.cs to Implab/src/Automaton/RegularExpressions/Token.cs
1 NO CONTENT: file renamed from Implab/Components/Disposable.cs to Implab/src/Components/Disposable.cs
1 NO CONTENT: file renamed from Implab/Components/DisposablePool.cs to Implab/src/Components/DisposablePool.cs
1 NO CONTENT: file renamed from Implab/Components/ExecutionState.cs to Implab/src/Components/ExecutionState.cs
1 NO CONTENT: file renamed from Implab/Components/IAsyncComponent.cs to Implab/src/Components/IAsyncComponent.cs
1 NO CONTENT: file renamed from Implab/Components/IFactory.cs to Implab/src/Components/IFactory.cs
1 NO CONTENT: file renamed from Implab/Components/IInitializable.cs to Implab/src/Components/IInitializable.cs
1 NO CONTENT: file renamed from Implab/Components/IRunnable.cs to Implab/src/Components/IRunnable.cs
1 NO CONTENT: file renamed from Implab/Components/IServiceLocator.cs to Implab/src/Components/IServiceLocator.cs
1 NO CONTENT: file renamed from Implab/Components/LazyAndWeak.cs to Implab/src/Components/LazyAndWeak.cs
1 NO CONTENT: file renamed from Implab/Components/ObjectPool.cs to Implab/src/Components/ObjectPool.cs
1 NO CONTENT: file renamed from Implab/Components/PollingComponent.cs to Implab/src/Components/PollingComponent.cs
1 NO CONTENT: file renamed from Implab/Components/RunnableComponent.cs to Implab/src/Components/RunnableComponent.cs
1 NO CONTENT: file renamed from Implab/Components/ServiceLocator.cs to Implab/src/Components/ServiceLocator.cs
1 NO CONTENT: file renamed from Implab/Components/StateChangeEventArgs.cs to Implab/src/Components/StateChangeEventArgs.cs
1 NO CONTENT: file renamed from Implab/CustomEqualityComparer.cs to Implab/src/CustomEqualityComparer.cs
1 NO CONTENT: file renamed from Implab/Deferred.cs to Implab/src/Deferred.cs
1 NO CONTENT: file renamed from Implab/Deferred`1.cs to Implab/src/Deferred`1.cs
1 NO CONTENT: file renamed from Implab/Diagnostics/ActivityScope.cs to Implab/src/Diagnostics/ActivityScope.cs
1 NO CONTENT: file renamed from Implab/Diagnostics/LogicalOperation.cs to Implab/src/Diagnostics/LogicalOperation.cs
1 NO CONTENT: file renamed from Implab/Diagnostics/LogicalOperationScope.cs to Implab/src/Diagnostics/LogicalOperationScope.cs
1 NO CONTENT: file renamed from Implab/Diagnostics/SimpleTraceListener.cs to Implab/src/Diagnostics/SimpleTraceListener.cs
1 NO CONTENT: file renamed from Implab/Diagnostics/Trace.cs to Implab/src/Diagnostics/Trace.cs
1 NO CONTENT: file renamed from Implab/Diagnostics/TraceChannel.cs to Implab/src/Diagnostics/TraceChannel.cs
1 NO CONTENT: file renamed from Implab/Diagnostics/TraceEventCodes.cs to Implab/src/Diagnostics/TraceEventCodes.cs
1 NO CONTENT: file renamed from Implab/Diagnostics/TraceRegistry.cs to Implab/src/Diagnostics/TraceRegistry.cs
1 NO CONTENT: file renamed from Implab/Diagnostics/TraceSourceAttribute.cs to Implab/src/Diagnostics/TraceSourceAttribute.cs
1 NO CONTENT: file renamed from Implab/Diagnostics/TraceSourceChannel.cs to Implab/src/Diagnostics/TraceSourceChannel.cs
1 NO CONTENT: file renamed from Implab/Diagnostics/TraceSourceChannel`1.cs to Implab/src/Diagnostics/TraceSourceChannel`1.cs
1 NO CONTENT: file renamed from Implab/ExceptionHelpers.cs to Implab/src/ExceptionHelpers.cs
1 NO CONTENT: file renamed from Implab/Formats/ByteAlphabet.cs to Implab/src/Formats/ByteAlphabet.cs
1 NO CONTENT: file renamed from Implab/Formats/CharAlphabet.cs to Implab/src/Formats/CharAlphabet.cs
1 NO CONTENT: file renamed from Implab/Formats/CharMap.cs to Implab/src/Formats/CharMap.cs
1 NO CONTENT: file renamed from Implab/Formats/FastInpurScanner.cs to Implab/src/Formats/FastInpurScanner.cs
1 NO CONTENT: file renamed from Implab/Formats/Grammar.cs to Implab/src/Formats/Grammar.cs
1 NO CONTENT: file renamed from Implab/Formats/InputScanner.cs to Implab/src/Formats/InputScanner.cs
1 NO CONTENT: file renamed from Implab/Formats/Json/JsonElementContext.cs to Implab/src/Formats/Json/JsonElementContext.cs
1 NO CONTENT: file renamed from Implab/Formats/Json/JsonElementType.cs to Implab/src/Formats/Json/JsonElementType.cs
1 NO CONTENT: file renamed from Implab/Formats/Json/JsonGrammar.cs to Implab/src/Formats/Json/JsonGrammar.cs
1 NO CONTENT: file renamed from Implab/Formats/Json/JsonReader.cs to Implab/src/Formats/Json/JsonReader.cs
1 NO CONTENT: file renamed from Implab/Formats/Json/JsonScanner.cs to Implab/src/Formats/Json/JsonScanner.cs
1 NO CONTENT: file renamed from Implab/Formats/Json/JsonStringScanner.cs to Implab/src/Formats/Json/JsonStringScanner.cs
1 NO CONTENT: file renamed from Implab/Formats/Json/JsonTextScanner.cs to Implab/src/Formats/Json/JsonTextScanner.cs
1 NO CONTENT: file renamed from Implab/Formats/Json/JsonTokenType.cs to Implab/src/Formats/Json/JsonTokenType.cs
1 NO CONTENT: file renamed from Implab/Formats/Json/JsonWriter.cs to Implab/src/Formats/Json/JsonWriter.cs
1 NO CONTENT: file renamed from Implab/Formats/Json/StringTranslator.cs to Implab/src/Formats/Json/StringTranslator.cs
1 NO CONTENT: file renamed from Implab/IDispatcher.cs to Implab/src/IDispatcher.cs
1 NO CONTENT: file renamed from Implab/IPromise.cs to Implab/src/IPromise.cs
1 NO CONTENT: file renamed from Implab/IPromiseT.cs to Implab/src/IPromiseT.cs
1 NO CONTENT: file renamed from Implab/IResolvable.cs to Implab/src/IResolvable.cs
1 NO CONTENT: file renamed from Implab/IResolvable`1.cs to Implab/src/IResolvable`1.cs
1 NO CONTENT: file renamed from Implab/Messaging/IConsumer.cs to Implab/src/Messaging/IConsumer.cs
1 NO CONTENT: file renamed from Implab/Messaging/IProducer.cs to Implab/src/Messaging/IProducer.cs
1 NO CONTENT: file renamed from Implab/Parallels/AsyncQueue.cs to Implab/src/Parallels/AsyncQueue.cs
1 NO CONTENT: file renamed from Implab/Parallels/BlockingQueue.cs to Implab/src/Parallels/BlockingQueue.cs
1 NO CONTENT: file renamed from Implab/Parallels/DispatchPool.cs to Implab/src/Parallels/DispatchPool.cs
1 NO CONTENT: file renamed from Implab/Parallels/SharedLock.cs to Implab/src/Parallels/SharedLock.cs
1 NO CONTENT: file renamed from Implab/Parallels/Signal.cs to Implab/src/Parallels/Signal.cs
1 NO CONTENT: file renamed from Implab/Parallels/SimpleAsyncQueue.cs to Implab/src/Parallels/SimpleAsyncQueue.cs
1 NO CONTENT: file renamed from Implab/Parallels/SyncContextDispatcher.cs to Implab/src/Parallels/SyncContextDispatcher.cs
1 NO CONTENT: file renamed from Implab/Parallels/ThreadPoolDispatcher.cs to Implab/src/Parallels/ThreadPoolDispatcher.cs
1 NO CONTENT: file renamed from Implab/Promise.cs to Implab/src/Promise.cs
1 NO CONTENT: file renamed from Implab/PromiseActionReaction.cs to Implab/src/PromiseActionReaction.cs
1 NO CONTENT: file renamed from Implab/PromiseActionReaction`1.cs to Implab/src/PromiseActionReaction`1.cs
1 NO CONTENT: file renamed from Implab/PromiseAll.cs to Implab/src/PromiseAll.cs
1 NO CONTENT: file renamed from Implab/PromiseAll`1.cs to Implab/src/PromiseAll`1.cs
1 NO CONTENT: file renamed from Implab/PromiseAwaiter.cs to Implab/src/PromiseAwaiter.cs
1 NO CONTENT: file renamed from Implab/PromiseAwaiter`1.cs to Implab/src/PromiseAwaiter`1.cs
1 NO CONTENT: file renamed from Implab/PromiseExecutor.cs to Implab/src/PromiseExecutor.cs
1 NO CONTENT: file renamed from Implab/PromiseExecutor`1.cs to Implab/src/PromiseExecutor`1.cs
1 NO CONTENT: file renamed from Implab/PromiseExtensions.cs to Implab/src/PromiseExtensions.cs
1 NO CONTENT: file renamed from Implab/PromiseFuncReaction`1.cs to Implab/src/PromiseFuncReaction`1.cs
1 NO CONTENT: file renamed from Implab/PromiseFuncReaction`2.cs to Implab/src/PromiseFuncReaction`2.cs
1 NO CONTENT: file renamed from Implab/PromiseHandler.cs to Implab/src/PromiseHandler.cs
1 NO CONTENT: file renamed from Implab/PromiseState.cs to Implab/src/PromiseState.cs
1 NO CONTENT: file renamed from Implab/PromiseTransientException.cs to Implab/src/PromiseTransientException.cs
1 NO CONTENT: file renamed from Implab/Promise`1.cs to Implab/src/Promise`1.cs
1 NO CONTENT: file renamed from Implab/RejectedPromise.cs to Implab/src/RejectedPromise.cs
1 NO CONTENT: file renamed from Implab/RejectedPromise`1.cs to Implab/src/RejectedPromise`1.cs
1 NO CONTENT: file renamed from Implab/ResolvedPromise.cs to Implab/src/ResolvedPromise.cs
1 NO CONTENT: file renamed from Implab/ResolvedPromise`1.cs to Implab/src/ResolvedPromise`1.cs
1 NO CONTENT: file renamed from Implab/Safe.cs to Implab/src/Safe.cs
1 NO CONTENT: file renamed from Implab/TaskHelpers.cs to Implab/src/TaskHelpers.cs
1 NO CONTENT: file renamed from Implab/Xml/JsonXmlCaseTransform.cs to Implab/src/Xml/JsonXmlCaseTransform.cs
1 NO CONTENT: file renamed from Implab/Xml/JsonXmlReader.cs to Implab/src/Xml/JsonXmlReader.cs
1 NO CONTENT: file renamed from Implab/Xml/JsonXmlReaderOptions.cs to Implab/src/Xml/JsonXmlReaderOptions.cs
1 NO CONTENT: file renamed from Implab/Xml/JsonXmlReaderPosition.cs to Implab/src/Xml/JsonXmlReaderPosition.cs
1 NO CONTENT: file renamed from Implab/Xml/SerializationHelpers.cs to Implab/src/Xml/SerializationHelpers.cs
1 NO CONTENT: file renamed from Implab/Xml/SerializersPool.cs to Implab/src/Xml/SerializersPool.cs
1 NO CONTENT: file renamed from Implab/Xml/XmlDefaultSerializer.cs to Implab/src/Xml/XmlDefaultSerializer.cs
1 NO CONTENT: file renamed from Implab/Xml/XmlNameContext.cs to Implab/src/Xml/XmlNameContext.cs
1 NO CONTENT: file renamed from Implab/Xml/XmlSerializerExtensions.cs to Implab/src/Xml/XmlSerializerExtensions.cs
1 NO CONTENT: file renamed from Implab/Xml/XmlSimpleAttribute.cs to Implab/src/Xml/XmlSimpleAttribute.cs
1 NO CONTENT: file renamed from Implab/Xml/XmlToJson.cs to Implab/src/Xml/XmlToJson.cs
1 NO CONTENT: file renamed from Implab/Xml/json.xsl to Implab/src/Xml/json.xsl
1 NO CONTENT: file renamed from Implab/Xml/readme.txt to Implab/src/Xml/readme.txt
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