##// END OF EJS Templates
code cleanup and refactoring
cin -
r281:e0916ddc9950 v3
parent child
Show More
@@ -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 : InjectionParameterElement {
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 InjectionParameterElement[] Items { get; set; }
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 InjectionParameterElement[] Parameters { get; set; }
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 : InjectionParameterElement {
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 : InjectionParameterElement {
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 InjectionParameterElement[0])
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 InjectionParameterElement[] Parameters { get; set; }
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 InjectionParameterElement Value { get; set; }
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 : InjectionParameterElement {
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 : InjectionParameterElement {
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 Данная библиоетка создавалась для загрузки и применения конфигурации к IoC контейнеру, она не предназначена для конфигурирования
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 контейнеру, в частности к Unity.
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` - определяет элементы которые могут быть использованы в конфигурации контейнера, предоставляет настроенный `XmlSerializer`.
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 Элемент верхнего уровня всегда `ContainerElemnt`, он используется для хранения набора элеметов, которые распознаются и выполняются `ContainerBuilder`.
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.10</Version>
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
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