Auto status change to "Under Review"
@@ -0,0 +1,12 | |||||
|
1 | using System; | |||
|
2 | using System.Xml.Serialization; | |||
|
3 | ||||
|
4 | namespace Implab.ServiceHost.Unity { | |||
|
5 | public abstract class AbstractInjectionParameter : IInjectionParameter { | |||
|
6 | ||||
|
7 | [XmlAttribute("type")] | |||
|
8 | public string TypeName { get; set; } | |||
|
9 | ||||
|
10 | public abstract void Visit(InjectionParameterBuilder builder); | |||
|
11 | } | |||
|
12 | } No newline at end of file |
@@ -0,0 +1,17 | |||||
|
1 | using System; | |||
|
2 | using System.Diagnostics; | |||
|
3 | ||||
|
4 | namespace Implab.Diagnostics | |||
|
5 | { | |||
|
6 | public class ChannelAdvertisementEventArgs : EventArgs { | |||
|
7 | internal ChannelAdvertisementEventArgs(object channelId, TraceSource source) { | |||
|
8 | ChannelId = channelId; | |||
|
9 | Source = source; | |||
|
10 | } | |||
|
11 | ||||
|
12 | public object ChannelId { get; private set; } | |||
|
13 | ||||
|
14 | public TraceSource Source { get; private set; } | |||
|
15 | ||||
|
16 | } | |||
|
17 | } No newline at end of file |
@@ -1,16 +1,27 | |||||
1 | <Project Sdk="Microsoft.NET.Sdk"> |
|
1 | <Project Sdk="Microsoft.NET.Sdk"> | |
2 |
|
2 | |||
3 | <PropertyGroup> |
|
3 | <PropertyGroup> | |
4 | <TargetFrameworks>netstandard2.0;net46</TargetFrameworks> |
|
4 | <TargetFrameworks>netstandard2.0;net46</TargetFrameworks> | |
5 | <FrameworkPathOverride Condition="'$(TargetFramework)'=='net46'">/usr/lib/mono/4.6-api/</FrameworkPathOverride> |
|
5 | <FrameworkPathOverride Condition="'$(TargetFramework)'=='net46'">/usr/lib/mono/4.6-api/</FrameworkPathOverride> | |
|
6 | <Authors>Sergey Smirnov</Authors> | |||
|
7 | <Title>Implab.SrviceHost library</Title> | |||
|
8 | <Description>Provides simple and flexible XML configuration for the Unity IoC</Description> | |||
|
9 | <Copyright>2018 Sergey Smirnov</Copyright> | |||
|
10 | <Version>1.0.0</Version> | |||
|
11 | <PackageLicenseUrl>https://hg.implab.org/pub/ImplabNet/file/tip/Implab/license.txt</PackageLicenseUrl> | |||
|
12 | <PackageProjectUrl>https://implab.org</PackageProjectUrl> | |||
|
13 | <RepositoryUrl>https://hg.implab.org/pub/ImplabNet/</RepositoryUrl> | |||
|
14 | <RepositoryType>mercurial</RepositoryType> | |||
|
15 | <PackageTags>IoC; Unity; Dependency Injection</PackageTags> | |||
|
16 | <TargetFrameworks>netstandard2.0;net46</TargetFrameworks> | |||
6 | </PropertyGroup> |
|
17 | </PropertyGroup> | |
7 |
|
18 | |||
8 | <ItemGroup> |
|
19 | <ItemGroup> | |
9 | <PackageReference Include="Unity" Version="5.8.5" /> |
|
20 | <PackageReference Include="Unity" Version="5.8.5" /> | |
10 | </ItemGroup> |
|
21 | </ItemGroup> | |
11 |
|
22 | |||
12 | <ItemGroup> |
|
23 | <ItemGroup> | |
13 | <ProjectReference Include="..\Implab\Implab.csproj" /> |
|
24 | <ProjectReference Include="..\Implab\Implab.csproj" /> | |
14 | </ItemGroup> |
|
25 | </ItemGroup> | |
15 |
|
26 | |||
16 | </Project> |
|
27 | </Project> |
@@ -1,20 +1,20 | |||||
1 | using System.Xml.Serialization; |
|
1 | using System.Xml.Serialization; | |
2 |
|
2 | |||
3 | namespace Implab.ServiceHost.Unity |
|
3 | namespace Implab.ServiceHost.Unity | |
4 | { |
|
4 | { | |
5 |
public class ArrayParameterElement : InjectionParameter |
|
5 | public class ArrayParameterElement : AbstractInjectionParameter { | |
6 |
|
6 | |||
7 | [XmlAttribute("itemsType")] |
|
7 | [XmlAttribute("itemsType")] | |
8 | public string ItemsType { get; set; } |
|
8 | public string ItemsType { get; set; } | |
9 |
|
9 | |||
10 | [XmlElement("dependency", typeof(DependencyParameterElement))] |
|
10 | [XmlElement("dependency", typeof(DependencyParameterElement))] | |
11 | [XmlElement("value", typeof(ValueParameterElement))] |
|
11 | [XmlElement("value", typeof(ValueParameterElement))] | |
12 | [XmlElement("serialized", typeof(SerializedParameterElement))] |
|
12 | [XmlElement("serialized", typeof(SerializedParameterElement))] | |
13 | [XmlElement("default", typeof(DefaultParameterElement))] |
|
13 | [XmlElement("default", typeof(DefaultParameterElement))] | |
14 |
public InjectionParameter |
|
14 | public AbstractInjectionParameter[] Items { get; set; } | |
15 |
|
15 | |||
16 | public override void Visit(InjectionParameterBuilder builder) { |
|
16 | public override void Visit(InjectionParameterBuilder builder) { | |
17 | builder.Visit(this); |
|
17 | builder.Visit(this); | |
18 | } |
|
18 | } | |
19 | } |
|
19 | } | |
20 | } No newline at end of file |
|
20 | } |
@@ -1,17 +1,17 | |||||
1 | using System.Xml.Serialization; |
|
1 | using System.Xml.Serialization; | |
2 |
|
2 | |||
3 | namespace Implab.ServiceHost.Unity { |
|
3 | namespace Implab.ServiceHost.Unity { | |
4 | public class ConstructorInjectionElement : AbstractMemberInjection { |
|
4 | public class ConstructorInjectionElement : AbstractMemberInjection { | |
5 |
|
5 | |||
6 | [XmlElement("dependency", typeof(DependencyParameterElement))] |
|
6 | [XmlElement("dependency", typeof(DependencyParameterElement))] | |
7 | [XmlElement("value", typeof(ValueParameterElement))] |
|
7 | [XmlElement("value", typeof(ValueParameterElement))] | |
8 | [XmlElement("serialized", typeof(SerializedParameterElement))] |
|
8 | [XmlElement("serialized", typeof(SerializedParameterElement))] | |
9 | [XmlElement("default", typeof(DefaultParameterElement))] |
|
9 | [XmlElement("default", typeof(DefaultParameterElement))] | |
10 | [XmlElement("array", typeof(ArrayParameterElement))] |
|
10 | [XmlElement("array", typeof(ArrayParameterElement))] | |
11 |
public InjectionParameter |
|
11 | public AbstractInjectionParameter[] Parameters { get; set; } | |
12 |
|
12 | |||
13 | public override void Visit(TypeRegistrationBuilder builder) { |
|
13 | public override void Visit(TypeRegistrationBuilder builder) { | |
14 | builder.Visit(this); |
|
14 | builder.Visit(this); | |
15 | } |
|
15 | } | |
16 | } |
|
16 | } | |
17 | } No newline at end of file |
|
17 | } |
@@ -1,13 +1,13 | |||||
1 | namespace Implab.ServiceHost.Unity |
|
1 | namespace Implab.ServiceHost.Unity | |
2 | { |
|
2 | { | |
3 |
public class DefaultParameterElement : InjectionParameter |
|
3 | public class DefaultParameterElement : AbstractInjectionParameter { | |
4 | public string Value { |
|
4 | public string Value { | |
5 | get { return null; } |
|
5 | get { return null; } | |
6 | } |
|
6 | } | |
7 |
|
7 | |||
8 | public override void Visit(InjectionParameterBuilder builder) { |
|
8 | public override void Visit(InjectionParameterBuilder builder) { | |
9 | var type = builder.ResolveInjectedValueType(TypeName); |
|
9 | var type = builder.ResolveInjectedValueType(TypeName); | |
10 | builder.SetValue(type, Safe.CreateDefaultValue(type)); |
|
10 | builder.SetValue(type, Safe.CreateDefaultValue(type)); | |
11 | } |
|
11 | } | |
12 | } |
|
12 | } | |
13 | } No newline at end of file |
|
13 | } |
@@ -1,17 +1,17 | |||||
1 | using System.Xml.Serialization; |
|
1 | using System.Xml.Serialization; | |
2 |
|
2 | |||
3 | namespace Implab.ServiceHost.Unity { |
|
3 | namespace Implab.ServiceHost.Unity { | |
4 |
public class DependencyParameterElement : InjectionParameter |
|
4 | public class DependencyParameterElement : AbstractInjectionParameter { | |
5 |
|
5 | |||
6 | [XmlAttribute("name")] |
|
6 | [XmlAttribute("name")] | |
7 | public string DependencyName { get; set; } |
|
7 | public string DependencyName { get; set; } | |
8 |
|
8 | |||
9 | [XmlAttribute("optional")] |
|
9 | [XmlAttribute("optional")] | |
10 | public bool Optional { get; set; } |
|
10 | public bool Optional { get; set; } | |
11 |
|
11 | |||
12 | public override void Visit(InjectionParameterBuilder builder) { |
|
12 | public override void Visit(InjectionParameterBuilder builder) { | |
13 | var type = builder.ResolveInjectedValueType(TypeName); |
|
13 | var type = builder.ResolveInjectedValueType(TypeName); | |
14 | builder.SetDependency(type, DependencyName, Optional); |
|
14 | builder.SetDependency(type, DependencyName, Optional); | |
15 | } |
|
15 | } | |
16 | } |
|
16 | } | |
17 | } No newline at end of file |
|
17 | } |
@@ -1,72 +1,73 | |||||
1 | using System; |
|
1 | using System; | |
2 | using System.Xml.Serialization; |
|
2 | using System.Xml.Serialization; | |
3 | using Implab.Components; |
|
3 | using Implab.Components; | |
4 |
|
4 | |||
5 | namespace Implab.ServiceHost.Unity { |
|
5 | namespace Implab.ServiceHost.Unity { | |
6 | /// <summary> |
|
6 | /// <summary> | |
7 | /// Расширяет стандартную регистрацию типа до фабрики, вместе с регистрацией |
|
7 | /// Расширяет стандартную регистрацию типа до фабрики, вместе с регистрацией | |
8 | /// самой фабрики создаются регистрации сервисов, которые она предоставляет. |
|
8 | /// самой фабрики создаются регистрации сервисов, которые она предоставляет. | |
9 | /// </summary> |
|
9 | /// </summary> | |
10 | public class FactoryElement : RegisterElement, ITypeRegistration { |
|
10 | public class FactoryElement : RegisterElement, ITypeRegistration { | |
11 |
|
11 | |||
12 | /// <summary> |
|
12 | /// <summary> | |
13 | /// Записи о сервисах, которые создаются данной фабрикой. |
|
13 | /// Записи о сервисах, которые создаются данной фабрикой. | |
14 | /// </summary> |
|
14 | /// </summary> | |
15 | /// <remarks> |
|
15 | /// <remarks> | |
16 | /// Сервисы, которые указаны в регистарциях они должны соответсвовать тому, |
|
16 | /// Сервисы, которые указаны в регистарциях они должны соответсвовать тому, | |
17 | /// что фабрика возвращает, но это остается на откуп контейнера |
|
17 | /// что фабрика возвращает, но это остается на откуп контейнера | |
18 | /// </remarks> |
|
18 | /// </remarks> | |
19 | [XmlElement("provides")] |
|
19 | [XmlElement("provides")] | |
20 | public ProvidesElement[] Provides { get; set; } |
|
20 | public ProvidesElement[] Provides { get; set; } | |
21 |
|
21 | |||
22 | /// <summary> |
|
22 | /// <summary> | |
23 | /// Переопределяет стандарное поведение регистрации типа в контейнере, |
|
23 | /// Переопределяет стандарное поведение регистрации типа в контейнере, | |
24 | /// дополняя его регистрацией фабричных методов для получения типов. |
|
24 | /// дополняя его регистрацией фабричных методов для получения типов. | |
25 | /// </summary> |
|
25 | /// </summary> | |
26 | /// <param name="builder">Объект для конфигурирования контейнера.</param> |
|
26 | /// <param name="builder">Объект для конфигурирования контейнера.</param> | |
27 | public override void Visit(ContainerBuilder builder) { |
|
27 | public override void Visit(ContainerBuilder builder) { | |
28 | var factoryType = GetRegistrationType(builder.ResolveType); |
|
28 | var factoryType = GetRegistrationType(builder.ResolveType); | |
29 |
|
29 | |||
30 | base.Visit(builder); |
|
30 | base.Visit(builder); | |
31 |
|
31 | |||
32 | if (Provides != null && Provides.Length > 0) { |
|
32 | if (Provides != null && Provides.Length > 0) { | |
33 | // если регистрации явно заданы, используеися информация из них |
|
33 | // если регистрации явно заданы, используеися информация из них | |
34 | foreach(var item in Provides) { |
|
34 | foreach(var item in Provides) { | |
35 | var activator = new FactoryActivator { |
|
35 | var activator = new FactoryActivator { | |
36 | Name = item.RegistrationName, |
|
36 | Name = item.RegistrationName, | |
37 | RegistrationType = builder.ResolveType(item.RegistrationType), |
|
37 | RegistrationType = builder.ResolveType(item.RegistrationType), | |
38 | FactoryName = Name, |
|
38 | FactoryName = Name, | |
39 | FactoryType = factoryType |
|
39 | FactoryType = factoryType, | |
|
40 | Lifetime = item.Lifetime.GetLifetime(builder) | |||
40 | }; |
|
41 | }; | |
41 | builder.Visit(activator); |
|
42 | builder.Visit(activator); | |
42 | } |
|
43 | } | |
43 | } else { |
|
44 | } else { | |
44 | // если регистрация явно не задана, в качестве сервиса для регистрации |
|
45 | // если регистрация явно не задана, в качестве сервиса для регистрации | |
45 | // используется тип создаваемый фабрикой, который будет добавлен в контейнер |
|
46 | // используется тип создаваемый фабрикой, который будет добавлен в контейнер | |
46 | // с темже именем, что и сама фабрика (разные типы могут иметь одно имя для регистрации) |
|
47 | // с темже именем, что и сама фабрика (разные типы могут иметь одно имя для регистрации) | |
47 | var providedType = ( |
|
48 | var providedType = ( | |
48 | factoryType.IsGenericType && factoryType.GetGenericTypeDefinition() == typeof(IFactory<>) ? |
|
49 | factoryType.IsGenericType && factoryType.GetGenericTypeDefinition() == typeof(IFactory<>) ? | |
49 | factoryType : |
|
50 | factoryType : | |
50 | factoryType.GetInterface(typeof(IFactory<>).FullName) |
|
51 | factoryType.GetInterface(typeof(IFactory<>).FullName) | |
51 | )? |
|
52 | )? | |
52 | .GetGenericArguments()[0]; |
|
53 | .GetGenericArguments()[0]; | |
53 |
|
54 | |||
54 | // не удалось определеить тип |
|
55 | // не удалось определеить тип | |
55 | if (providedType == null) |
|
56 | if (providedType == null) | |
56 | throw new ArgumentException("Failed to determine a type provided by the factory"); |
|
57 | throw new ArgumentException("Failed to determine a type provided by the factory"); | |
57 |
|
58 | |||
58 | if (providedType.IsGenericParameter) |
|
59 | if (providedType.IsGenericParameter) | |
59 | throw new ArgumentException("Can't register a generic type paramter as a service"); |
|
60 | throw new ArgumentException("Can't register a generic type paramter as a service"); | |
60 |
|
61 | |||
61 | var activator = new FactoryActivator { |
|
62 | var activator = new FactoryActivator { | |
62 | Name = Name, |
|
63 | Name = Name, | |
63 | RegistrationType = providedType, |
|
64 | RegistrationType = providedType, | |
64 | FactoryName = Name, |
|
65 | FactoryName = Name, | |
65 | FactoryType = factoryType |
|
66 | FactoryType = factoryType | |
66 | }; |
|
67 | }; | |
67 |
|
68 | |||
68 | builder.Visit(activator); |
|
69 | builder.Visit(activator); | |
69 | } |
|
70 | } | |
70 | } |
|
71 | } | |
71 | } |
|
72 | } | |
72 | } No newline at end of file |
|
73 | } |
@@ -1,137 +1,137 | |||||
1 | using System; |
|
1 | using System; | |
2 | using System.Collections; |
|
2 | using System.Collections; | |
3 | using System.Collections.Generic; |
|
3 | using System.Collections.Generic; | |
4 | using System.ComponentModel; |
|
4 | using System.ComponentModel; | |
5 | using System.Linq; |
|
5 | using System.Linq; | |
6 | using System.Xml.Serialization; |
|
6 | using System.Xml.Serialization; | |
7 | using Unity.Injection; |
|
7 | using Unity.Injection; | |
8 |
|
8 | |||
9 | namespace Implab.ServiceHost.Unity { |
|
9 | namespace Implab.ServiceHost.Unity { | |
10 |
|
10 | |||
11 | public class InjectionParameterBuilder { |
|
11 | public class InjectionParameterBuilder { | |
12 |
|
12 | |||
13 | readonly TypeResolver m_resolver; |
|
13 | readonly TypeResolver m_resolver; | |
14 |
|
14 | |||
15 | public Type DefaultType { get; private set; } |
|
15 | public Type DefaultType { get; private set; } | |
16 |
|
16 | |||
17 | public Type ValueType { get; private set; } |
|
17 | public Type ValueType { get; private set; } | |
18 |
|
18 | |||
19 | object m_value; |
|
19 | object m_value; | |
20 |
|
20 | |||
21 | public object Value { |
|
21 | public object Value { | |
22 | get { |
|
22 | get { | |
23 | if (!ValueSpecified) |
|
23 | if (!ValueSpecified) | |
24 | throw new InvalidOperationException("The regular value must be set (dependency or array are not situable in this context)"); |
|
24 | throw new InvalidOperationException("The regular value must be set (dependency or array are not situable in this context)"); | |
25 | return m_value; |
|
25 | return m_value; | |
26 | } |
|
26 | } | |
27 | } |
|
27 | } | |
28 |
|
28 | |||
29 | public bool ValueSpecified { get; private set; } |
|
29 | public bool ValueSpecified { get; private set; } | |
30 |
|
30 | |||
31 | InjectionParameterValue m_injection; |
|
31 | InjectionParameterValue m_injection; | |
32 |
|
32 | |||
33 | public InjectionParameterValue Injection { |
|
33 | public InjectionParameterValue Injection { | |
34 | get { |
|
34 | get { | |
35 | if (m_injection == null) |
|
35 | if (m_injection == null) | |
36 | throw new InvalidOperationException("The injection parameter is not specified"); |
|
36 | throw new InvalidOperationException("The injection parameter is not specified"); | |
37 | return m_injection; |
|
37 | return m_injection; | |
38 | } |
|
38 | } | |
39 | } |
|
39 | } | |
40 |
|
40 | |||
41 | public bool InjectionSpecified { |
|
41 | public bool InjectionSpecified { | |
42 | get { return m_injection != null; } |
|
42 | get { return m_injection != null; } | |
43 | } |
|
43 | } | |
44 |
|
44 | |||
45 | internal InjectionParameterBuilder(TypeResolver resolver, Type defaultType) { |
|
45 | internal InjectionParameterBuilder(TypeResolver resolver, Type defaultType) { | |
46 | m_resolver = resolver; |
|
46 | m_resolver = resolver; | |
47 | DefaultType = defaultType; |
|
47 | DefaultType = defaultType; | |
48 | } |
|
48 | } | |
49 |
|
49 | |||
50 | public Type ResolveInjectedValueType(string typeSpec) { |
|
50 | public Type ResolveInjectedValueType(string typeSpec) { | |
51 | if (string.IsNullOrEmpty(typeSpec)) { |
|
51 | if (string.IsNullOrEmpty(typeSpec)) { | |
52 | if (DefaultType == null) |
|
52 | if (DefaultType == null) | |
53 | throw new Exception("The type must be specified"); |
|
53 | throw new Exception("The type must be specified"); | |
54 | return DefaultType; |
|
54 | return DefaultType; | |
55 | } |
|
55 | } | |
56 | return m_resolver.Resolve(typeSpec, true); |
|
56 | return m_resolver.Resolve(typeSpec, true); | |
57 | } |
|
57 | } | |
58 |
|
58 | |||
59 | public Type ResolveType(string typeSpec) { |
|
59 | public Type ResolveType(string typeSpec) { | |
60 | return string.IsNullOrEmpty(typeSpec) ? null : m_resolver.Resolve(typeSpec, true); |
|
60 | return string.IsNullOrEmpty(typeSpec) ? null : m_resolver.Resolve(typeSpec, true); | |
61 | } |
|
61 | } | |
62 |
|
62 | |||
63 | public void SetValue(Type type, object value) { |
|
63 | public void SetValue(Type type, object value) { | |
64 | Safe.ArgumentNotNull(type, nameof(type)); |
|
64 | Safe.ArgumentNotNull(type, nameof(type)); | |
65 |
|
65 | |||
66 | ValueType = type; |
|
66 | ValueType = type; | |
67 | m_value = value; |
|
67 | m_value = value; | |
68 | ValueSpecified = true; |
|
68 | ValueSpecified = true; | |
69 |
|
69 | |||
70 | m_injection = new InjectionParameter(type, value); |
|
70 | m_injection = new InjectionParameter(type, value); | |
71 | } |
|
71 | } | |
72 |
|
72 | |||
73 | public void SetDependency(Type type, string name, bool optional) { |
|
73 | public void SetDependency(Type type, string name, bool optional) { | |
74 | Safe.ArgumentNotNull(type, nameof(type)); |
|
74 | Safe.ArgumentNotNull(type, nameof(type)); | |
75 |
|
75 | |||
76 | ValueType = type; |
|
76 | ValueType = type; | |
77 | ValueSpecified = false; |
|
77 | ValueSpecified = false; | |
78 | m_value = null; |
|
78 | m_value = null; | |
79 |
|
79 | |||
80 | m_injection = optional ? (InjectionParameterValue)new OptionalParameter(type, name) : new ResolvedParameter(type, name); |
|
80 | m_injection = optional ? (InjectionParameterValue)new OptionalParameter(type, name) : new ResolvedParameter(type, name); | |
81 | } |
|
81 | } | |
82 |
|
82 | |||
83 | internal void Visit(ArrayParameterElement arrayParameter) { |
|
83 | internal void Visit(ArrayParameterElement arrayParameter) { | |
84 | Type itemsType = null; |
|
84 | Type itemsType = null; | |
85 | var arrayType = string.IsNullOrEmpty(arrayParameter.TypeName) ? null : ResolveType(arrayParameter.TypeName); |
|
85 | var arrayType = string.IsNullOrEmpty(arrayParameter.TypeName) ? null : ResolveType(arrayParameter.TypeName); | |
86 |
|
86 | |||
87 | if (arrayType == null) |
|
87 | if (arrayType == null) | |
88 | arrayType = DefaultType; |
|
88 | arrayType = DefaultType; | |
89 |
|
89 | |||
90 |
|
90 | |||
91 | if (!string.IsNullOrEmpty(arrayParameter.ItemsType)) { |
|
91 | if (!string.IsNullOrEmpty(arrayParameter.ItemsType)) { | |
92 | itemsType = ResolveType(arrayParameter.ItemsType); |
|
92 | itemsType = ResolveType(arrayParameter.ItemsType); | |
93 | arrayType = itemsType.MakeArrayType(); |
|
93 | arrayType = itemsType.MakeArrayType(); | |
94 | } else { |
|
94 | } else { | |
95 | itemsType = GetItemsType(arrayType); |
|
95 | itemsType = GetItemsType(arrayType); | |
96 | } |
|
96 | } | |
97 |
|
97 | |||
98 | if (itemsType == null) |
|
98 | if (itemsType == null) | |
99 | throw new Exception("Failed to determine array elements type"); |
|
99 | throw new Exception("Failed to determine array elements type"); | |
100 |
|
100 | |||
101 |
InjectionParameterValue[] injections = (arrayParameter.Items ?? new InjectionParameter |
|
101 | InjectionParameterValue[] injections = (arrayParameter.Items ?? new AbstractInjectionParameter[0]) | |
102 | .Select(x => { |
|
102 | .Select(x => { | |
103 | var builder = new InjectionParameterBuilder(m_resolver, itemsType); |
|
103 | var builder = new InjectionParameterBuilder(m_resolver, itemsType); | |
104 | x.Visit(builder); |
|
104 | x.Visit(builder); | |
105 | return builder.Injection; |
|
105 | return builder.Injection; | |
106 | }) |
|
106 | }) | |
107 | .ToArray(); |
|
107 | .ToArray(); | |
108 |
|
108 | |||
109 | var array = itemsType.IsGenericParameter ? |
|
109 | var array = itemsType.IsGenericParameter ? | |
110 | (InjectionParameterValue)new GenericResolvedArrayParameter(itemsType.Name, injections) : |
|
110 | (InjectionParameterValue)new GenericResolvedArrayParameter(itemsType.Name, injections) : | |
111 | new ResolvedArrayParameter(itemsType, injections); |
|
111 | new ResolvedArrayParameter(itemsType, injections); | |
112 |
|
112 | |||
113 | ValueType = arrayType; |
|
113 | ValueType = arrayType; | |
114 | m_value = null; |
|
114 | m_value = null; | |
115 | ValueSpecified = false; |
|
115 | ValueSpecified = false; | |
116 |
|
116 | |||
117 | m_injection = array; |
|
117 | m_injection = array; | |
118 | } |
|
118 | } | |
119 |
|
119 | |||
120 | Type GetItemsType(Type collectionType) { |
|
120 | Type GetItemsType(Type collectionType) { | |
121 | if (collectionType == null) |
|
121 | if (collectionType == null) | |
122 | return null; |
|
122 | return null; | |
123 |
|
123 | |||
124 | Type itemsType = null; |
|
124 | Type itemsType = null; | |
125 |
|
125 | |||
126 | if (collectionType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) { |
|
126 | if (collectionType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) { | |
127 | itemsType = collectionType.GetGenericArguments()[0]; |
|
127 | itemsType = collectionType.GetGenericArguments()[0]; | |
128 | } else if (collectionType == typeof(IEnumerable)) { |
|
128 | } else if (collectionType == typeof(IEnumerable)) { | |
129 | itemsType = typeof(object); |
|
129 | itemsType = typeof(object); | |
130 | } else { |
|
130 | } else { | |
131 | itemsType = collectionType.GetInterface(typeof(IEnumerable<>).FullName)?.GetGenericArguments()[0]; |
|
131 | itemsType = collectionType.GetInterface(typeof(IEnumerable<>).FullName)?.GetGenericArguments()[0]; | |
132 | } |
|
132 | } | |
133 |
|
133 | |||
134 | return itemsType; |
|
134 | return itemsType; | |
135 | } |
|
135 | } | |
136 | } |
|
136 | } | |
137 | } No newline at end of file |
|
137 | } |
@@ -1,20 +1,20 | |||||
1 | using System.Xml.Serialization; |
|
1 | using System.Xml.Serialization; | |
2 |
|
2 | |||
3 | namespace Implab.ServiceHost.Unity { |
|
3 | namespace Implab.ServiceHost.Unity { | |
4 | public class MethodInjectionElement : AbstractMemberInjection { |
|
4 | public class MethodInjectionElement : AbstractMemberInjection { | |
5 |
|
5 | |||
6 | [XmlAttribute("name")] |
|
6 | [XmlAttribute("name")] | |
7 | public string Name { get; set; } |
|
7 | public string Name { get; set; } | |
8 |
|
8 | |||
9 | [XmlElement("dependency", typeof(DependencyParameterElement))] |
|
9 | [XmlElement("dependency", typeof(DependencyParameterElement))] | |
10 | [XmlElement("value", typeof(ValueParameterElement))] |
|
10 | [XmlElement("value", typeof(ValueParameterElement))] | |
11 | [XmlElement("serialized", typeof(SerializedParameterElement))] |
|
11 | [XmlElement("serialized", typeof(SerializedParameterElement))] | |
12 | [XmlElement("default", typeof(DefaultParameterElement))] |
|
12 | [XmlElement("default", typeof(DefaultParameterElement))] | |
13 | [XmlElement("array", typeof(ArrayParameterElement))] |
|
13 | [XmlElement("array", typeof(ArrayParameterElement))] | |
14 |
public InjectionParameter |
|
14 | public AbstractInjectionParameter[] Parameters { get; set; } | |
15 |
|
15 | |||
16 | public override void Visit(TypeRegistrationBuilder context) { |
|
16 | public override void Visit(TypeRegistrationBuilder context) { | |
17 | context.Visit(this); |
|
17 | context.Visit(this); | |
18 | } |
|
18 | } | |
19 | } |
|
19 | } | |
20 | } No newline at end of file |
|
20 | } |
@@ -1,20 +1,20 | |||||
1 | using System.Xml.Serialization; |
|
1 | using System.Xml.Serialization; | |
2 |
|
2 | |||
3 | namespace Implab.ServiceHost.Unity { |
|
3 | namespace Implab.ServiceHost.Unity { | |
4 | public class PropertyInjectionElement : AbstractMemberInjection { |
|
4 | public class PropertyInjectionElement : AbstractMemberInjection { | |
5 |
|
5 | |||
6 | [XmlAttribute("name")] |
|
6 | [XmlAttribute("name")] | |
7 | public string Name { get; set; } |
|
7 | public string Name { get; set; } | |
8 |
|
8 | |||
9 | [XmlElement("dependency", typeof(DependencyParameterElement))] |
|
9 | [XmlElement("dependency", typeof(DependencyParameterElement))] | |
10 | [XmlElement("value", typeof(ValueParameterElement))] |
|
10 | [XmlElement("value", typeof(ValueParameterElement))] | |
11 | [XmlElement("serialized", typeof(SerializedParameterElement))] |
|
11 | [XmlElement("serialized", typeof(SerializedParameterElement))] | |
12 | [XmlElement("default", typeof(DefaultParameterElement))] |
|
12 | [XmlElement("default", typeof(DefaultParameterElement))] | |
13 | [XmlElement("array", typeof(ArrayParameterElement))] |
|
13 | [XmlElement("array", typeof(ArrayParameterElement))] | |
14 |
public InjectionParameter |
|
14 | public AbstractInjectionParameter Value { get; set; } | |
15 |
|
15 | |||
16 | public override void Visit(TypeRegistrationBuilder context) { |
|
16 | public override void Visit(TypeRegistrationBuilder context) { | |
17 | context.Visit(this); |
|
17 | context.Visit(this); | |
18 | } |
|
18 | } | |
19 | } |
|
19 | } | |
20 | } No newline at end of file |
|
20 | } |
@@ -1,11 +1,17 | |||||
1 | using System.Xml.Serialization; |
|
1 | using System.Xml.Serialization; | |
2 |
|
2 | |||
3 | namespace Implab.ServiceHost.Unity { |
|
3 | namespace Implab.ServiceHost.Unity { | |
4 | public class ProvidesElement { |
|
4 | public class ProvidesElement { | |
5 | [XmlAttribute("type")] |
|
5 | [XmlAttribute("type")] | |
6 | public string RegistrationType { get; set; } |
|
6 | public string RegistrationType { get; set; } | |
7 |
|
7 | |||
8 | [XmlAttribute("name")] |
|
8 | [XmlAttribute("name")] | |
9 | public string RegistrationName { get; set; } |
|
9 | public string RegistrationName { get; set; } | |
|
10 | ||||
|
11 | [XmlElement("signleton", typeof(SingletonLifetimeElement))] | |||
|
12 | [XmlElement("context", typeof(ContextLifetimeElement))] | |||
|
13 | [XmlElement("container", typeof(ContainerLifetimeElement))] | |||
|
14 | [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))] | |||
|
15 | public LifetimeElement Lifetime {get; set;} | |||
10 | } |
|
16 | } | |
11 | } No newline at end of file |
|
17 | } |
@@ -1,33 +1,33 | |||||
1 | using System; |
|
1 | using System; | |
2 | using System.Xml; |
|
2 | using System.Xml; | |
3 | using System.Xml.Schema; |
|
3 | using System.Xml.Schema; | |
4 | using System.Xml.Serialization; |
|
4 | using System.Xml.Serialization; | |
5 |
|
5 | |||
6 | namespace Implab.ServiceHost.Unity |
|
6 | namespace Implab.ServiceHost.Unity | |
7 | { |
|
7 | { | |
8 |
public class SerializedParameterElement : InjectionParameter |
|
8 | public class SerializedParameterElement : AbstractInjectionParameter { | |
9 | [XmlAttribute("href")] |
|
9 | [XmlAttribute("href")] | |
10 | public string Location { get; set; } |
|
10 | public string Location { get; set; } | |
11 |
|
11 | |||
12 | [XmlAnyElement] |
|
12 | [XmlAnyElement] | |
13 | public XmlElement[] Content { get; set; } |
|
13 | public XmlElement[] Content { get; set; } | |
14 |
|
14 | |||
15 | public XmlReader GetReader() { |
|
15 | public XmlReader GetReader() { | |
16 | if (!string.IsNullOrEmpty(Location)) |
|
16 | if (!string.IsNullOrEmpty(Location)) | |
17 | return XmlReader.Create(Location); |
|
17 | return XmlReader.Create(Location); | |
18 | if (Content != null && Content.Length > 0) |
|
18 | if (Content != null && Content.Length > 0) | |
19 | return Content[0].CreateNavigator().ReadSubtree(); |
|
19 | return Content[0].CreateNavigator().ReadSubtree(); | |
20 |
|
20 | |||
21 | throw new Exception("No content found, expected XML document"); |
|
21 | throw new Exception("No content found, expected XML document"); | |
22 | } |
|
22 | } | |
23 |
|
23 | |||
24 | public override void Visit(InjectionParameterBuilder builder) { |
|
24 | public override void Visit(InjectionParameterBuilder builder) { | |
25 | var type = builder.ResolveInjectedValueType(TypeName); |
|
25 | var type = builder.ResolveInjectedValueType(TypeName); | |
26 |
|
26 | |||
27 | var serializer = new XmlSerializer(type); |
|
27 | var serializer = new XmlSerializer(type); | |
28 | using(var reader = GetReader()) |
|
28 | using(var reader = GetReader()) | |
29 | builder.SetValue(type, serializer.Deserialize(reader)); |
|
29 | builder.SetValue(type, serializer.Deserialize(reader)); | |
30 |
|
30 | |||
31 | } |
|
31 | } | |
32 | } |
|
32 | } | |
33 | } No newline at end of file |
|
33 | } |
@@ -1,21 +1,21 | |||||
1 | using System.ComponentModel; |
|
1 | using System.ComponentModel; | |
2 | using System.Xml.Serialization; |
|
2 | using System.Xml.Serialization; | |
3 |
|
3 | |||
4 | namespace Implab.ServiceHost.Unity { |
|
4 | namespace Implab.ServiceHost.Unity { | |
5 |
public class ValueParameterElement : InjectionParameter |
|
5 | public class ValueParameterElement : AbstractInjectionParameter { | |
6 | [XmlAttribute("value")] |
|
6 | [XmlAttribute("value")] | |
7 | public string Value { get; set; } |
|
7 | public string Value { get; set; } | |
8 |
|
8 | |||
9 | [XmlText] |
|
9 | [XmlText] | |
10 | public string Text { get; set; } |
|
10 | public string Text { get; set; } | |
11 |
|
11 | |||
12 | string GetTextValue() { |
|
12 | string GetTextValue() { | |
13 | return string.IsNullOrEmpty(Value) ? Text : Value; |
|
13 | return string.IsNullOrEmpty(Value) ? Text : Value; | |
14 | } |
|
14 | } | |
15 |
|
15 | |||
16 | public override void Visit(InjectionParameterBuilder builder) { |
|
16 | public override void Visit(InjectionParameterBuilder builder) { | |
17 | var type = builder.ResolveInjectedValueType(TypeName); |
|
17 | var type = builder.ResolveInjectedValueType(TypeName); | |
18 | builder.SetValue(type, TypeDescriptor.GetConverter(type).ConvertFromString(GetTextValue())); |
|
18 | builder.SetValue(type, TypeDescriptor.GetConverter(type).ConvertFromString(GetTextValue())); | |
19 | } |
|
19 | } | |
20 | } |
|
20 | } | |
21 | } No newline at end of file |
|
21 | } |
@@ -1,100 +1,113 | |||||
1 | # XML Конфигурация IoC контейнера |
|
1 | # XML Конфигурация IoC контейнера | |
2 |
|
2 | |||
3 |
|
|
3 | Библиоетка создавалась для загрузки и применения конфигурации к IoC контейнеру, она не предназначена для конфигурирования | |
4 | контейнера во время выполнения, большинство контейнеров уже обладают данным функционалом. |
|
4 | контейнера во время выполнения, большинство контейнеров уже обладают данным функционалом. | |
5 |
|
5 | |||
6 | На данный момент поддерживается единственный вид контейнера - [Unity Container](https://unitycontainer.github.io/) |
|
6 | На данный момент поддерживается единственный вид контейнера - [Unity Container](https://unitycontainer.github.io/) | |
7 |
|
7 | |||
8 | Unity уже обладает средствами загрузки конфигурации из XML, данная библиотека позволяет решать следующие задачи |
|
8 | Unity уже обладает средствами загрузки конфигурации из XML, данная библиотека реализует аналогичный функционал, кроме того, позволяет решать следующие задачи: | |
9 |
|
9 | |||
10 | - Конфигурация является простым Xml документом, который можно получить из любого источика и не ограничивается `.config` файлами приложения |
|
10 | - Конфигурация является простым Xml документом, который можно получить из любого источика и не ограничивается `.config` файлами приложения | |
11 | - Включение существующе конфигурации `<include href='config.xml'/>` в текущую |
|
11 | - Включение существующе конфигурации `<include href='config.xml'/>` в текущую | |
12 | - Поддержка сериализованных объектов в качестве регистраций сервисов и параметров |
|
12 | - Поддержка сериализованных объектов в качестве регистраций сервисов и параметров | |
13 | - Описание зависимостей может быть расширено собсвтенными элементами с произвольной структурой |
|
13 | - Поддержка специфиакции генериков любой вложенности, например `Dictionary{Foo,Bar{Int32}}` | |
14 | - Поддержка специфиакции генериков любой вложенности `Dictionary{Foo,Bar{Int32}}` |
|
14 | - Поддержка фабрик в XML конфигурации | |
|
15 | - Расширение схемы XML конфигурации собственными элементами | |||
15 |
|
16 | |||
16 | ## Общая архитектура |
|
17 | ## Общая архитектура | |
17 |
|
18 | |||
18 |
`Implab.ServiceHost.Unity` содержит в себе классы для загрузки и применения XML конфигурации к IoC контейнеру |
|
19 | Пространство имен `Implab.ServiceHost.Unity` содержит в себе классы для загрузки и применения XML конфигурации к IoC контейнеру. | |
|
20 | ||||
|
21 | Применение конфигурации к контейнеру состоит из следующих основных шагов: | |||
19 |
|
22 | |||
20 | 1. Настраивается схема `ContainerConfigurationSchema` |
|
23 | 1. Настраивается схема `ContainerConfigurationSchema` XML конфигурации контейнера | |
21 | 2. Загружается документ и десереализуется в виде `ContainerElement` |
|
24 | 2. Загружается документ и десереализуется в виде `ContainerElement` | |
22 | 3. Создается `ContainerBuilder` при помощи которого применяются настройки из `ContainerElement` |
|
25 | 3. Создается `ContainerBuilder` при помощи которого применяются настройки из `ContainerElement` к контейнеру | |
23 |
|
26 | |||
24 |
`ContainerConfigurationSchema` |
|
27 | Схема `ContainerConfigurationSchema` определяет элементы документа, которые могут быть использованы в конфигурации контейнера, позволяет создать `XmlSerializer`, который используется для загрузки конфигурации. | |
25 |
|
28 | |||
26 | `ContainerBuilder` - основной класс, который используется для применения конфигурации к контейнеру, добавляет записи регистрации сервисов. |
|
29 | `ContainerBuilder` - основной класс, который используется для применения конфигурации к контейнеру, он добавляет записи регистрации сервисов из конфигурации в контейнер. | |
27 |
|
30 | |||
28 | `ContainerElement` - Корневой элемент конфигурации, который загружается из документа. |
|
31 | `ContainerElement` - Конфигурация контейнера, которая загружается из документа, состоит из директив для `ContainerBuilder`, а также из записей регистрации сервисов. | |
29 |
|
32 | |||
30 | Классы заканчивающиеся словом `Builder` используются для применения конфигурации к контейнеру, |
|
33 | В библиотеки приняты следующие правила именования классов: | |
31 | классы заканчивающиеся на `Element` содержат информацию о конфигурации и десериализуются из исходного документа. |
|
34 | ||
|
35 | - `***Builder` используются для применения конфигурации к контейнеру, | |||
|
36 | - `***Element` содержат информацию о конфигурации и десериализуются из исходного документа. | |||
32 |
|
37 | |||
33 | ## Структура конфигурации контейнера |
|
38 | ## Структура конфигурации контейнера | |
34 |
|
39 | |||
35 |
Элемент верхнего уровня всегда ` |
|
40 | Элемент верхнего уровня всегда `container`, он используется для хранения набора элеметов, которые распознаются и выполняются `ContainerBuilder`. | |
36 |
|
41 | |||
37 | Все элементы, входящие в контейнер наследуются от абстрактного класса `ContainerItemElement`, |
|
42 | Все элементы, входящие в контейнер наследуются от абстрактного класса `ContainerItemElement`, | |
38 | который позволяет получить текущий `ContainerBuilder` и выполнить над ним какие-либо действия. |
|
43 | который позволяет получить текущий `ContainerBuilder` и выполнить над ним какие-либо действия. | |
39 |
|
44 | |||
40 | Примерами элементов контейнера могут быть |
|
45 | Основные элементы конфигурации контенейра | |
41 |
|
46 | |||
42 | - `<include href='config.xml'/>` - включение конфигурации из указанного места |
|
47 | - `<include href='config.xml'/>` - включение конфигурации из указанного места | |
43 | - `<namespace name='My.App'/>` - добавление пространства имен для поиска типов |
|
48 | - `<namespace name='My.App'/>` - добавление пространства имен для поиска типов | |
44 | - `<register type='MyGenericType{}'/>` - добавление в контейнер регистрации типа ``My.App.MyGenericType`1`` |
|
49 | - `<register type='MyGenericType{}'/>` - добавление в контейнер регистрации типа ``My.App.MyGenericType`1`` | |
|
50 | - `<factory type='IFactory{Foo}' mapTo ='MyFactory'/>` - фабрика, регистрирует свой тип, а также тип `Foo` | |||
|
51 | - `<serialized />` - сериализованный экземпляр объекта, использует `XmlSerializer` для десериализации | |||
|
52 | - `<value />` - значение объекта в виде строки, используется для простых типов | |||
45 |
|
53 | |||
46 | Полный набор элементов, доступных для использования в контейнере определяет схема `ContainerConfigurationSchema`, |
|
54 | Полный набор элементов, доступных для использования в контейнере определяет схема `ContainerConfigurationSchema`, | |
47 | разработчик может расширить контейнер совими собственными элементами зарегистрировав их в схеме. |
|
55 | разработчик может расширить контейнер совими собственными элементами зарегистрировав их в схеме. | |
48 |
|
56 | |||
|
57 | ### register | |||
|
58 | ||||
|
59 | О | |||
|
60 | ||||
|
61 | ||||
49 | Например, мы используем компоненту `MyHttpClient` для загрузки данных |
|
62 | Например, мы используем компоненту `MyHttpClient` для загрузки данных | |
50 |
|
63 | |||
51 | ```xml |
|
64 | ```xml | |
52 | <register type="IClient" mapTo="MyHttpClient"> |
|
65 | <register type="IClient" mapTo="MyHttpClient"> | |
53 | <property name="proxy"> |
|
66 | <property name="proxy"> | |
54 | <value>socks5://proxy1.my.company</value> |
|
67 | <value>socks5://proxy1.my.company</value> | |
55 | </property> |
|
68 | </property> | |
56 | </register> |
|
69 | </register> | |
57 | ``` |
|
70 | ``` | |
58 |
|
71 | |||
59 | При частом использовании можно сделать описание конфигурации несколько проще, |
|
72 | При частом использовании можно сделать описание конфигурации несколько проще, | |
60 | описав новый эелемент конфигурации |
|
73 | описав новый эелемент конфигурации | |
61 |
|
74 | |||
62 | ```csharp |
|
75 | ```csharp | |
63 | public class MyHttpClientElement : ContainerItemElement { |
|
76 | public class MyHttpClientElement : ContainerItemElement { | |
64 |
|
77 | |||
65 | public string Proxy { get; set; } |
|
78 | public string Proxy { get; set; } | |
66 |
|
79 | |||
67 | public override void Visit(ContainerBuilder builder) { |
|
80 | public override void Visit(ContainerBuilder builder) { | |
68 | // создаем описание элемента |
|
81 | // создаем описание элемента | |
69 | var registration = new RegistrationElement { |
|
82 | var registration = new RegistrationElement { | |
70 | RegistrationType = "IClient", |
|
83 | RegistrationType = "IClient", | |
71 | ImplementationType = "My.App.MyHttpClient", |
|
84 | ImplementationType = "My.App.MyHttpClient", | |
72 | Injectors = new [] { |
|
85 | Injectors = new [] { | |
73 | new PropertyInjectionElement { |
|
86 | new PropertyInjectionElement { | |
74 | Name = "Proxy", |
|
87 | Name = "Proxy", | |
75 | Value = ValueParameterElement { |
|
88 | Value = ValueParameterElement { | |
76 | Value = Proxy |
|
89 | Value = Proxy | |
77 | } |
|
90 | } | |
78 | } |
|
91 | } | |
79 | } |
|
92 | } | |
80 | }; |
|
93 | }; | |
81 |
|
94 | |||
82 | // применяем созданное описание к контейнеру |
|
95 | // применяем созданное описание к контейнеру | |
83 | builder.Visit(registration) |
|
96 | builder.Visit(registration) | |
84 | } |
|
97 | } | |
85 | } |
|
98 | } | |
86 | ``` |
|
99 | ``` | |
87 |
|
100 | |||
88 | Регистрируем новый элемент в схеме |
|
101 | Регистрируем новый элемент в схеме | |
89 |
|
102 | |||
90 | ```csharp |
|
103 | ```csharp | |
91 | schema.RegisterContainerElement<MyHttpClientElement>("http"); |
|
104 | schema.RegisterContainerElement<MyHttpClientElement>("http"); | |
92 | ``` |
|
105 | ``` | |
93 |
|
106 | |||
94 | Используем новый элемент в конфигурации |
|
107 | Используем новый элемент в конфигурации | |
95 |
|
108 | |||
96 | ```xml |
|
109 | ```xml | |
97 | <http> |
|
110 | <http> | |
98 | <proxy>socks5://proxy1.my.company</propxy> |
|
111 | <proxy>socks5://proxy1.my.company</propxy> | |
99 | </http> |
|
112 | </http> | |
100 | ``` No newline at end of file |
|
113 | ``` |
@@ -1,144 +1,161 | |||||
1 | using System; |
|
1 | // enable System.Diagnostics trace methods | |
|
2 | #define TRACE | |||
|
3 | ||||
|
4 | using System; | |||
2 | using System.Collections.Generic; |
|
5 | using System.Collections.Generic; | |
3 | using System.Diagnostics; |
|
6 | using System.Diagnostics; | |
4 | using System.Linq; |
|
7 | using System.Linq; | |
5 | using System.Text; |
|
8 | using System.Text; | |
6 | using System.Threading; |
|
9 | using System.Threading; | |
7 | using System.Threading.Tasks; |
|
10 | using System.Threading.Tasks; | |
8 |
|
11 | |||
9 | namespace Implab.Diagnostics { |
|
12 | namespace Implab.Diagnostics { | |
10 | public static class Trace<T> { |
|
13 | public static class Trace<T> { | |
11 |
|
14 | |||
12 | public static TraceSource TraceSource { get; } = new TraceSource(typeof(T).Name); |
|
15 | static Lazy<TraceSource> _traceSource = new Lazy<TraceSource>(CreateChannel, LazyThreadSafetyMode.ExecutionAndPublication); | |
|
16 | ||||
|
17 | static int _nextId; | |||
|
18 | ||||
|
19 | static TraceSource CreateChannel() { | |||
|
20 | var id = Interlocked.Increment(ref _nextId); | |||
|
21 | return new TraceSource(typeof(T).Name); | |||
|
22 | } | |||
|
23 | ||||
|
24 | public static TraceSource TraceSource { get { return _traceSource.Value; } } | |||
|
25 | ||||
|
26 | public static IDisposable Subscribe() { | |||
|
27 | ||||
|
28 | throw new NotImplementedException(); | |||
|
29 | } | |||
13 |
|
30 | |||
14 | #if NETFX_TRACE_BUG |
|
31 | #if NETFX_TRACE_BUG | |
15 | readonly static AsyncLocal<object> m_currentOperation = new AsyncLocal<object>(); |
|
32 | readonly static AsyncLocal<object> m_currentOperation = new AsyncLocal<object>(); | |
16 | #endif |
|
33 | #endif | |
17 |
|
34 | |||
18 | /// <summary> |
|
35 | /// <summary> | |
19 | /// Starts the logical operation nested to the current operation nested to the current one. |
|
36 | /// Starts the logical operation nested to the current operation nested to the current one. | |
20 | /// </summary> |
|
37 | /// </summary> | |
21 | public static void StartLogicalOperation() { |
|
38 | public static void StartLogicalOperation() { | |
22 | Trace.CorrelationManager.StartLogicalOperation(); |
|
39 | Trace.CorrelationManager.StartLogicalOperation(); | |
23 |
|
40 | |||
24 | } |
|
41 | } | |
25 |
|
42 | |||
26 | /// <summary> |
|
43 | /// <summary> | |
27 | /// Starts the logical operation with the specified name, this name is usefull in logs. |
|
44 | /// Starts the logical operation with the specified name, this name is usefull in logs. | |
28 | /// </summary> |
|
45 | /// </summary> | |
29 | /// <param name="name">Name.</param> |
|
46 | /// <param name="name">Name.</param> | |
30 | #if NETFX_TRACE_BUG |
|
47 | #if NETFX_TRACE_BUG | |
31 | public static void StartLogicalOperation(object name) { |
|
48 | public static void StartLogicalOperation(object name) { | |
32 | m_currentOperation.Value = name; |
|
49 | m_currentOperation.Value = name; | |
33 | Trace.CorrelationManager.StartLogicalOperation(name); |
|
50 | Trace.CorrelationManager.StartLogicalOperation(name); | |
34 | } |
|
51 | } | |
35 | #else |
|
52 | #else | |
36 | public static void StartLogicalOperation(object name) { |
|
53 | public static void StartLogicalOperation(object name) { | |
37 | Trace.CorrelationManager.StartLogicalOperation(name); |
|
54 | Trace.CorrelationManager.StartLogicalOperation(name); | |
38 | } |
|
55 | } | |
39 | #endif |
|
56 | #endif | |
40 |
|
57 | |||
41 | /// <summary> |
|
58 | /// <summary> | |
42 | /// Ends the logical operation and restores the previous one. |
|
59 | /// Ends the logical operation and restores the previous one. | |
43 | /// </summary> |
|
60 | /// </summary> | |
44 | public static void StopLogicalOperation() { |
|
61 | public static void StopLogicalOperation() { | |
45 | Trace.CorrelationManager.StopLogicalOperation(); |
|
62 | Trace.CorrelationManager.StopLogicalOperation(); | |
46 | } |
|
63 | } | |
47 |
|
64 | |||
48 | /// <summary> |
|
65 | /// <summary> | |
49 | /// Writes a debug message. |
|
66 | /// Writes a debug message. | |
50 | /// </summary> |
|
67 | /// </summary> | |
51 | /// <param name="format">Format.</param> |
|
68 | /// <param name="format">Format.</param> | |
52 | /// <param name="arguments">Arguments.</param> |
|
69 | /// <param name="arguments">Arguments.</param> | |
53 | [Conditional("DEBUG")] |
|
70 | [Conditional("DEBUG")] | |
54 | public static void Debug(string format, params object[] arguments) { |
|
71 | public static void Debug(string format, params object[] arguments) { | |
55 |
|
72 | |||
56 | } |
|
73 | } | |
57 |
|
74 | |||
58 | /// <summary> |
|
75 | /// <summary> | |
59 | /// Writes an informational message. |
|
76 | /// Writes an informational message. | |
60 | /// </summary> |
|
77 | /// </summary> | |
61 | /// <param name="format">Format.</param> |
|
78 | /// <param name="format">Format.</param> | |
62 | /// <param name="arguments">Arguments.</param> |
|
79 | /// <param name="arguments">Arguments.</param> | |
63 | [Conditional("TRACE")] |
|
80 | [Conditional("TRACE")] | |
64 | public static void Log(string format, params object[] arguments) { |
|
81 | public static void Log(string format, params object[] arguments) { | |
65 | TraceSource.TraceEvent(TraceEventType.Information, 0, format, arguments); |
|
82 | TraceSource.TraceEvent(TraceEventType.Information, 0, format, arguments); | |
66 | } |
|
83 | } | |
67 |
|
84 | |||
68 | /// <summary> |
|
85 | /// <summary> | |
69 | /// Writes a warning message. |
|
86 | /// Writes a warning message. | |
70 | /// </summary> |
|
87 | /// </summary> | |
71 | /// <param name="format">Format.</param> |
|
88 | /// <param name="format">Format.</param> | |
72 | /// <param name="arguments">Arguments.</param> |
|
89 | /// <param name="arguments">Arguments.</param> | |
73 | public static void Warn(string format, params object[] arguments) { |
|
90 | public static void Warn(string format, params object[] arguments) { | |
74 | TraceSource.TraceEvent(TraceEventType.Warning, 0, format, arguments); |
|
91 | TraceSource.TraceEvent(TraceEventType.Warning, 0, format, arguments); | |
75 | } |
|
92 | } | |
76 |
|
93 | |||
77 | /// <summary> |
|
94 | /// <summary> | |
78 | /// Writes a error message. |
|
95 | /// Writes a error message. | |
79 | /// </summary> |
|
96 | /// </summary> | |
80 | /// <param name="format">Format.</param> |
|
97 | /// <param name="format">Format.</param> | |
81 | /// <param name="arguments">Arguments.</param> |
|
98 | /// <param name="arguments">Arguments.</param> | |
82 | public static void Error(string format, params object[] arguments) { |
|
99 | public static void Error(string format, params object[] arguments) { | |
83 | TraceSource.TraceEvent(TraceEventType.Error, 0, format, arguments); |
|
100 | TraceSource.TraceEvent(TraceEventType.Error, 0, format, arguments); | |
84 | } |
|
101 | } | |
85 |
|
102 | |||
86 | public static void Error(Exception err) { |
|
103 | public static void Error(Exception err) { | |
87 | TraceSource.TraceData(TraceEventType.Error, 0, err); |
|
104 | TraceSource.TraceData(TraceEventType.Error, 0, err); | |
88 | } |
|
105 | } | |
89 |
|
106 | |||
90 | /// <summary> |
|
107 | /// <summary> | |
91 | /// This method save the current activity, and transfers to the specified activity, |
|
108 | /// This method save the current activity, and transfers to the specified activity, | |
92 | /// emits <see cref="TraceEventType.Start"/> and returns a scope of the new |
|
109 | /// emits <see cref="TraceEventType.Start"/> and returns a scope of the new | |
93 | /// activity. |
|
110 | /// activity. | |
94 | /// </summary> |
|
111 | /// </summary> | |
95 | /// <param name="activityName">The name of the new activity/</param> |
|
112 | /// <param name="activityName">The name of the new activity/</param> | |
96 | /// <param name="activityId">The identifier of the activity to which |
|
113 | /// <param name="activityId">The identifier of the activity to which | |
97 | /// the control will be transferred</param> |
|
114 | /// the control will be transferred</param> | |
98 | /// <returns>A scope of the new activity, dispose it to transfer |
|
115 | /// <returns>A scope of the new activity, dispose it to transfer | |
99 | /// the control back to the original activity.</returns> |
|
116 | /// the control back to the original activity.</returns> | |
100 | public static ActivityScope TransferActivity(string activityName, Guid activityId) { |
|
117 | public static ActivityScope TransferActivity(string activityName, Guid activityId) { | |
101 | var prev = Trace.CorrelationManager.ActivityId; |
|
118 | var prev = Trace.CorrelationManager.ActivityId; | |
102 |
|
119 | |||
103 | TraceSource.TraceTransfer(0, "Transfer", activityId); |
|
120 | TraceSource.TraceTransfer(0, "Transfer", activityId); | |
104 | Trace.CorrelationManager.ActivityId = activityId; |
|
121 | Trace.CorrelationManager.ActivityId = activityId; | |
105 | TraceSource.TraceEvent(TraceEventType.Start, 0, activityName); |
|
122 | TraceSource.TraceEvent(TraceEventType.Start, 0, activityName); | |
106 |
|
123 | |||
107 | return new ActivityScope(TraceSource, prev, 0, activityName); |
|
124 | return new ActivityScope(TraceSource, prev, 0, activityName); | |
108 | } |
|
125 | } | |
109 |
|
126 | |||
110 | /// <summary> |
|
127 | /// <summary> | |
111 | /// Emits <see cref="TraceEventType.Start"/> and returns a scope of the |
|
128 | /// Emits <see cref="TraceEventType.Start"/> and returns a scope of the | |
112 | /// activity. |
|
129 | /// activity. | |
113 | /// </summary> |
|
130 | /// </summary> | |
114 | /// <param name="activityName">The name of the activity to start</param> |
|
131 | /// <param name="activityName">The name of the activity to start</param> | |
115 | /// <returns>A scope of the new activity, dispose it to emit |
|
132 | /// <returns>A scope of the new activity, dispose it to emit | |
116 | /// <see cref="TraceEventType.Stop"/> for the current activity.</returns> |
|
133 | /// <see cref="TraceEventType.Stop"/> for the current activity.</returns> | |
117 | public static ActivityScope StartActivity(string activityName) { |
|
134 | public static ActivityScope StartActivity(string activityName) { | |
118 | if (Trace.CorrelationManager.ActivityId == Guid.Empty) |
|
135 | if (Trace.CorrelationManager.ActivityId == Guid.Empty) | |
119 | Trace.CorrelationManager.ActivityId = Guid.NewGuid(); |
|
136 | Trace.CorrelationManager.ActivityId = Guid.NewGuid(); | |
120 |
|
137 | |||
121 | var prev = Trace.CorrelationManager.ActivityId; |
|
138 | var prev = Trace.CorrelationManager.ActivityId; | |
122 |
|
139 | |||
123 | TraceSource.TraceEvent(TraceEventType.Start, 0, activityName); |
|
140 | TraceSource.TraceEvent(TraceEventType.Start, 0, activityName); | |
124 | return new ActivityScope(TraceSource, prev, 0, activityName); |
|
141 | return new ActivityScope(TraceSource, prev, 0, activityName); | |
125 | } |
|
142 | } | |
126 |
|
143 | |||
127 | /// <summary> |
|
144 | /// <summary> | |
128 | /// Creates new <see cref="LogicalOperation(string)"/> and calls |
|
145 | /// Creates new <see cref="LogicalOperation(string)"/> and calls | |
129 | /// to <see cref="CorrelationManager.StartLogicalOperation(object)"/> |
|
146 | /// to <see cref="CorrelationManager.StartLogicalOperation(object)"/> | |
130 | /// passing the created operation as identity. Calls |
|
147 | /// passing the created operation as identity. Calls | |
131 | /// <see cref="TraceSource.TraceData(TraceEventType, int, object)"/> |
|
148 | /// <see cref="TraceSource.TraceData(TraceEventType, int, object)"/> | |
132 | /// to notify listeners on operation start. |
|
149 | /// to notify listeners on operation start. | |
133 | /// </summary> |
|
150 | /// </summary> | |
134 | /// <param name="name">The name of the logical operation.</param> |
|
151 | /// <param name="name">The name of the logical operation.</param> | |
135 | /// <returns>Logical operation scope, disposing it will stop |
|
152 | /// <returns>Logical operation scope, disposing it will stop | |
136 | /// logical operation and notify trace listeners.</returns> |
|
153 | /// logical operation and notify trace listeners.</returns> | |
137 | public static LogicalOperationScope LogicalOperation(string name) { |
|
154 | public static LogicalOperationScope LogicalOperation(string name) { | |
138 | var operation = new LogicalOperation(name); |
|
155 | var operation = new LogicalOperation(name); | |
139 | TraceSource.TraceData(TraceEventType.Information, TraceEventCodes.StartLogicalOperation, operation); |
|
156 | TraceSource.TraceData(TraceEventType.Information, TraceEventCodes.StartLogicalOperation, operation); | |
140 | StartLogicalOperation(operation); |
|
157 | StartLogicalOperation(operation); | |
141 | return new LogicalOperationScope(TraceSource, operation); |
|
158 | return new LogicalOperationScope(TraceSource, operation); | |
142 | } |
|
159 | } | |
143 | } |
|
160 | } | |
144 | } |
|
161 | } |
@@ -1,26 +1,26 | |||||
1 | <Project Sdk="Microsoft.NET.Sdk"> |
|
1 | <Project Sdk="Microsoft.NET.Sdk"> | |
2 |
|
2 | |||
3 | <PropertyGroup> |
|
3 | <PropertyGroup> | |
4 | <Authors>Sergey Smirnov</Authors> |
|
4 | <Authors>Sergey Smirnov</Authors> | |
5 | <Title>Implab library</Title> |
|
5 | <Title>Implab library</Title> | |
6 | <Description>Provides some helper clesses like XML serialization helpers, JSON XML reader, |
|
6 | <Description>Provides some helper clesses like XML serialization helpers, JSON XML reader, | |
7 | JSON pull-parser, ECMA-style promises, lightweight synchonization routines Signal |
|
7 | JSON pull-parser, ECMA-style promises, lightweight synchonization routines Signal | |
8 | and SharedLock, Trace helpers on top of System.Diagnostics, ObjectPool etc. |
|
8 | and SharedLock, Trace helpers on top of System.Diagnostics, ObjectPool etc. | |
9 | </Description> |
|
9 | </Description> | |
10 | <Copyright>2012-2018 Sergey Smirnov</Copyright> |
|
10 | <Copyright>2012-2018 Sergey Smirnov</Copyright> | |
11 |
<Version>3.0.1 |
|
11 | <Version>3.0.12</Version> | |
12 | <PackageLicenseUrl>https://hg.implab.org/pub/ImplabNet/file/tip/Implab/license.txt</PackageLicenseUrl> |
|
12 | <PackageLicenseUrl>https://hg.implab.org/pub/ImplabNet/file/tip/Implab/license.txt</PackageLicenseUrl> | |
13 | <PackageProjectUrl>https://implab.org</PackageProjectUrl> |
|
13 | <PackageProjectUrl>https://implab.org</PackageProjectUrl> | |
14 | <RepositoryUrl>https://hg.implab.org/pub/ImplabNet/</RepositoryUrl> |
|
14 | <RepositoryUrl>https://hg.implab.org/pub/ImplabNet/</RepositoryUrl> | |
15 | <RepositoryType>mercurial</RepositoryType> |
|
15 | <RepositoryType>mercurial</RepositoryType> | |
16 | <PackageTags>IMPLAB;Json pull-parser;Json Xml;async;diagnostics;serialization;</PackageTags> |
|
16 | <PackageTags>IMPLAB;Json pull-parser;Json Xml;async;diagnostics;serialization;</PackageTags> | |
17 | <TargetFrameworks>netstandard2.0;net46</TargetFrameworks> |
|
17 | <TargetFrameworks>netstandard2.0;net46</TargetFrameworks> | |
18 | <FrameworkPathOverride Condition="'$(TargetFramework)'=='net46' and '$(OSTYPE)'=='linux'">/usr/lib/mono/4.5/</FrameworkPathOverride> |
|
18 | <FrameworkPathOverride Condition="'$(TargetFramework)'=='net46' and '$(OSTYPE)'=='linux'">/usr/lib/mono/4.5/</FrameworkPathOverride> | |
19 | <DefineConstants Condition="'$(TargetFramework)'=='net46'">NETFX_TRACE_BUG;$(DefineConstants)</DefineConstants> |
|
19 | <DefineConstants Condition="'$(TargetFramework)'=='net46'">NETFX_TRACE_BUG;$(DefineConstants)</DefineConstants> | |
20 | </PropertyGroup> |
|
20 | </PropertyGroup> | |
21 |
|
21 | |||
22 | <ItemGroup> |
|
22 | <ItemGroup> | |
23 | <EmbeddedResource Include="Xml\json.xsl"/> |
|
23 | <EmbeddedResource Include="Xml\json.xsl"/> | |
24 | </ItemGroup> |
|
24 | </ItemGroup> | |
25 |
|
25 | |||
26 | </Project> |
|
26 | </Project> |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 3
ok, latest stable version should be in default
You need to be logged in to leave comments.
Login now