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
