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 |
@@ -3,6 +3,17 | |||||
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> |
@@ -2,7 +2,7 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; } | |
@@ -11,7 +11,7 namespace Implab.ServiceHost.Unity | |||||
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); |
@@ -8,7 +8,7 namespace Implab.ServiceHost.Unity { | |||||
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); |
@@ -1,6 +1,6 | |||||
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 | } |
@@ -1,7 +1,7 | |||||
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; } |
@@ -36,7 +36,8 namespace Implab.ServiceHost.Unity { | |||||
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 | } |
@@ -98,7 +98,7 namespace Implab.ServiceHost.Unity { | |||||
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); |
@@ -11,7 +11,7 namespace Implab.ServiceHost.Unity { | |||||
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); |
@@ -11,7 +11,7 namespace Implab.ServiceHost.Unity { | |||||
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); |
@@ -7,5 +7,11 namespace Implab.ServiceHost.Unity { | |||||
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 | } |
@@ -5,7 +5,7 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 |
@@ -2,7 +2,7 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 |
@@ -1,51 +1,64 | |||||
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 |
@@ -1,4 +1,7 | |||||
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; | |
@@ -9,7 +12,21 using System.Threading.Tasks; | |||||
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>(); |
@@ -8,7 +8,7 | |||||
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> |
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