# HG changeset patch
# User cin
# Date 2018-06-01 18:35:24
# Node ID e0916ddc9950e268a0f21983b278951f21b62942
# Parent f07be402ab0265b61f768a329ba6eef5fdbda66b
code cleanup and refactoring
diff --git a/Implab.ServiceHost/Implab.ServiceHost.csproj b/Implab.ServiceHost/Implab.ServiceHost.csproj
--- a/Implab.ServiceHost/Implab.ServiceHost.csproj
+++ b/Implab.ServiceHost/Implab.ServiceHost.csproj
@@ -3,6 +3,17 @@
netstandard2.0;net46/usr/lib/mono/4.6-api/
+ Sergey Smirnov
+ Implab.SrviceHost library
+ Provides simple and flexible XML configuration for the Unity IoC
+ 2018 Sergey Smirnov
+ 1.0.0
+ https://hg.implab.org/pub/ImplabNet/file/tip/Implab/license.txt
+ https://implab.org
+ https://hg.implab.org/pub/ImplabNet/
+ mercurial
+ IoC; Unity; Dependency Injection
+ netstandard2.0;net46
diff --git a/Implab.ServiceHost/Unity/AbstractInjectionParameter.cs b/Implab.ServiceHost/Unity/AbstractInjectionParameter.cs
new file mode 100644
--- /dev/null
+++ b/Implab.ServiceHost/Unity/AbstractInjectionParameter.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Xml.Serialization;
+
+namespace Implab.ServiceHost.Unity {
+ public abstract class AbstractInjectionParameter : IInjectionParameter {
+
+ [XmlAttribute("type")]
+ public string TypeName { get; set; }
+
+ public abstract void Visit(InjectionParameterBuilder builder);
+ }
+}
\ No newline at end of file
diff --git a/Implab.ServiceHost/Unity/ArrayParameterElement.cs b/Implab.ServiceHost/Unity/ArrayParameterElement.cs
--- a/Implab.ServiceHost/Unity/ArrayParameterElement.cs
+++ b/Implab.ServiceHost/Unity/ArrayParameterElement.cs
@@ -2,7 +2,7 @@ using System.Xml.Serialization;
namespace Implab.ServiceHost.Unity
{
- public class ArrayParameterElement : InjectionParameterElement {
+ public class ArrayParameterElement : AbstractInjectionParameter {
[XmlAttribute("itemsType")]
public string ItemsType { get; set; }
@@ -11,7 +11,7 @@ namespace Implab.ServiceHost.Unity
[XmlElement("value", typeof(ValueParameterElement))]
[XmlElement("serialized", typeof(SerializedParameterElement))]
[XmlElement("default", typeof(DefaultParameterElement))]
- public InjectionParameterElement[] Items { get; set; }
+ public AbstractInjectionParameter[] Items { get; set; }
public override void Visit(InjectionParameterBuilder builder) {
builder.Visit(this);
diff --git a/Implab.ServiceHost/Unity/ConstructorInjectionElement.cs b/Implab.ServiceHost/Unity/ConstructorInjectionElement.cs
--- a/Implab.ServiceHost/Unity/ConstructorInjectionElement.cs
+++ b/Implab.ServiceHost/Unity/ConstructorInjectionElement.cs
@@ -8,7 +8,7 @@ namespace Implab.ServiceHost.Unity {
[XmlElement("serialized", typeof(SerializedParameterElement))]
[XmlElement("default", typeof(DefaultParameterElement))]
[XmlElement("array", typeof(ArrayParameterElement))]
- public InjectionParameterElement[] Parameters { get; set; }
+ public AbstractInjectionParameter[] Parameters { get; set; }
public override void Visit(TypeRegistrationBuilder builder) {
builder.Visit(this);
diff --git a/Implab.ServiceHost/Unity/DefaultParameterElement.cs b/Implab.ServiceHost/Unity/DefaultParameterElement.cs
--- a/Implab.ServiceHost/Unity/DefaultParameterElement.cs
+++ b/Implab.ServiceHost/Unity/DefaultParameterElement.cs
@@ -1,6 +1,6 @@
namespace Implab.ServiceHost.Unity
{
- public class DefaultParameterElement : InjectionParameterElement {
+ public class DefaultParameterElement : AbstractInjectionParameter {
public string Value {
get { return null; }
}
diff --git a/Implab.ServiceHost/Unity/DependencyParameterElement.cs b/Implab.ServiceHost/Unity/DependencyParameterElement.cs
--- a/Implab.ServiceHost/Unity/DependencyParameterElement.cs
+++ b/Implab.ServiceHost/Unity/DependencyParameterElement.cs
@@ -1,7 +1,7 @@
using System.Xml.Serialization;
namespace Implab.ServiceHost.Unity {
- public class DependencyParameterElement : InjectionParameterElement {
+ public class DependencyParameterElement : AbstractInjectionParameter {
[XmlAttribute("name")]
public string DependencyName { get; set; }
diff --git a/Implab.ServiceHost/Unity/FactoryElement.cs b/Implab.ServiceHost/Unity/FactoryElement.cs
--- a/Implab.ServiceHost/Unity/FactoryElement.cs
+++ b/Implab.ServiceHost/Unity/FactoryElement.cs
@@ -36,7 +36,8 @@ namespace Implab.ServiceHost.Unity {
Name = item.RegistrationName,
RegistrationType = builder.ResolveType(item.RegistrationType),
FactoryName = Name,
- FactoryType = factoryType
+ FactoryType = factoryType,
+ Lifetime = item.Lifetime.GetLifetime(builder)
};
builder.Visit(activator);
}
diff --git a/Implab.ServiceHost/Unity/InjectionParameterElement.cs b/Implab.ServiceHost/Unity/InjectionParameterElement.cs
deleted file mode 100644
--- a/Implab.ServiceHost/Unity/InjectionParameterElement.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-using System.Xml.Serialization;
-
-namespace Implab.ServiceHost.Unity {
- public abstract class InjectionParameterElement : IInjectionParameter {
-
- [XmlAttribute("type")]
- public string TypeName { get; set; }
-
- public abstract void Visit(InjectionParameterBuilder builder);
- }
-}
\ No newline at end of file
diff --git a/Implab.ServiceHost/Unity/InjectionValueBuilder.cs b/Implab.ServiceHost/Unity/InjectionValueBuilder.cs
--- a/Implab.ServiceHost/Unity/InjectionValueBuilder.cs
+++ b/Implab.ServiceHost/Unity/InjectionValueBuilder.cs
@@ -98,7 +98,7 @@ namespace Implab.ServiceHost.Unity {
if (itemsType == null)
throw new Exception("Failed to determine array elements type");
- InjectionParameterValue[] injections = (arrayParameter.Items ?? new InjectionParameterElement[0])
+ InjectionParameterValue[] injections = (arrayParameter.Items ?? new AbstractInjectionParameter[0])
.Select(x => {
var builder = new InjectionParameterBuilder(m_resolver, itemsType);
x.Visit(builder);
diff --git a/Implab.ServiceHost/Unity/MethodInjectionElement.cs b/Implab.ServiceHost/Unity/MethodInjectionElement.cs
--- a/Implab.ServiceHost/Unity/MethodInjectionElement.cs
+++ b/Implab.ServiceHost/Unity/MethodInjectionElement.cs
@@ -11,7 +11,7 @@ namespace Implab.ServiceHost.Unity {
[XmlElement("serialized", typeof(SerializedParameterElement))]
[XmlElement("default", typeof(DefaultParameterElement))]
[XmlElement("array", typeof(ArrayParameterElement))]
- public InjectionParameterElement[] Parameters { get; set; }
+ public AbstractInjectionParameter[] Parameters { get; set; }
public override void Visit(TypeRegistrationBuilder context) {
context.Visit(this);
diff --git a/Implab.ServiceHost/Unity/PropertyInjectionElement.cs b/Implab.ServiceHost/Unity/PropertyInjectionElement.cs
--- a/Implab.ServiceHost/Unity/PropertyInjectionElement.cs
+++ b/Implab.ServiceHost/Unity/PropertyInjectionElement.cs
@@ -11,7 +11,7 @@ namespace Implab.ServiceHost.Unity {
[XmlElement("serialized", typeof(SerializedParameterElement))]
[XmlElement("default", typeof(DefaultParameterElement))]
[XmlElement("array", typeof(ArrayParameterElement))]
- public InjectionParameterElement Value { get; set; }
+ public AbstractInjectionParameter Value { get; set; }
public override void Visit(TypeRegistrationBuilder context) {
context.Visit(this);
diff --git a/Implab.ServiceHost/Unity/ProvidesElement.cs b/Implab.ServiceHost/Unity/ProvidesElement.cs
--- a/Implab.ServiceHost/Unity/ProvidesElement.cs
+++ b/Implab.ServiceHost/Unity/ProvidesElement.cs
@@ -7,5 +7,11 @@ namespace Implab.ServiceHost.Unity {
[XmlAttribute("name")]
public string RegistrationName { get; set; }
+
+ [XmlElement("signleton", typeof(SingletonLifetimeElement))]
+ [XmlElement("context", typeof(ContextLifetimeElement))]
+ [XmlElement("container", typeof(ContainerLifetimeElement))]
+ [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
+ public LifetimeElement Lifetime {get; set;}
}
}
\ No newline at end of file
diff --git a/Implab.ServiceHost/Unity/SerializedParameterElement.cs b/Implab.ServiceHost/Unity/SerializedParameterElement.cs
--- a/Implab.ServiceHost/Unity/SerializedParameterElement.cs
+++ b/Implab.ServiceHost/Unity/SerializedParameterElement.cs
@@ -5,7 +5,7 @@ using System.Xml.Serialization;
namespace Implab.ServiceHost.Unity
{
- public class SerializedParameterElement : InjectionParameterElement {
+ public class SerializedParameterElement : AbstractInjectionParameter {
[XmlAttribute("href")]
public string Location { get; set; }
diff --git a/Implab.ServiceHost/Unity/ValueParameterElement.cs b/Implab.ServiceHost/Unity/ValueParameterElement.cs
--- a/Implab.ServiceHost/Unity/ValueParameterElement.cs
+++ b/Implab.ServiceHost/Unity/ValueParameterElement.cs
@@ -2,7 +2,7 @@ using System.ComponentModel;
using System.Xml.Serialization;
namespace Implab.ServiceHost.Unity {
- public class ValueParameterElement : InjectionParameterElement {
+ public class ValueParameterElement : AbstractInjectionParameter {
[XmlAttribute("value")]
public string Value { get; set; }
diff --git a/Implab.ServiceHost/docs/XmlConfiguration.md b/Implab.ServiceHost/docs/XmlConfiguration.md
--- a/Implab.ServiceHost/docs/XmlConfiguration.md
+++ b/Implab.ServiceHost/docs/XmlConfiguration.md
@@ -1,51 +1,64 @@
# XML Конфигурация IoC контейнера
-Данная библиоетка создавалась для загрузки и применения конфигурации к IoC контейнеру, она не предназначена для конфигурирования
+Библиоетка создавалась для загрузки и применения конфигурации к IoC контейнеру, она не предназначена для конфигурирования
контейнера во время выполнения, большинство контейнеров уже обладают данным функционалом.
На данный момент поддерживается единственный вид контейнера - [Unity Container](https://unitycontainer.github.io/)
-Unity уже обладает средствами загрузки конфигурации из XML, данная библиотека позволяет решать следующие задачи
+Unity уже обладает средствами загрузки конфигурации из XML, данная библиотека реализует аналогичный функционал, кроме того, позволяет решать следующие задачи:
- Конфигурация является простым Xml документом, который можно получить из любого источика и не ограничивается `.config` файлами приложения
- Включение существующе конфигурации `` в текущую
- Поддержка сериализованных объектов в качестве регистраций сервисов и параметров
-- Описание зависимостей может быть расширено собсвтенными элементами с произвольной структурой
-- Поддержка специфиакции генериков любой вложенности `Dictionary{Foo,Bar{Int32}}`
+- Поддержка специфиакции генериков любой вложенности, например `Dictionary{Foo,Bar{Int32}}`
+- Поддержка фабрик в XML конфигурации
+- Расширение схемы XML конфигурации собственными элементами
## Общая архитектура
-`Implab.ServiceHost.Unity` содержит в себе классы для загрузки и применения XML конфигурации к IoC контейнеру, в частности к Unity.
+Пространство имен `Implab.ServiceHost.Unity` содержит в себе классы для загрузки и применения XML конфигурации к IoC контейнеру.
+
+Применение конфигурации к контейнеру состоит из следующих основных шагов:
-1. Настраивается схема `ContainerConfigurationSchema`
+1. Настраивается схема `ContainerConfigurationSchema` XML конфигурации контейнера
2. Загружается документ и десереализуется в виде `ContainerElement`
-3. Создается `ContainerBuilder` при помощи которого применяются настройки из `ContainerElement`
+3. Создается `ContainerBuilder` при помощи которого применяются настройки из `ContainerElement` к контейнеру
-`ContainerConfigurationSchema` - определяет элементы которые могут быть использованы в конфигурации контейнера, предоставляет настроенный `XmlSerializer`.
+Схема `ContainerConfigurationSchema` определяет элементы документа, которые могут быть использованы в конфигурации контейнера, позволяет создать `XmlSerializer`, который используется для загрузки конфигурации.
-`ContainerBuilder` - основной класс, который используется для применения конфигурации к контейнеру, добавляет записи регистрации сервисов.
+`ContainerBuilder` - основной класс, который используется для применения конфигурации к контейнеру, он добавляет записи регистрации сервисов из конфигурации в контейнер.
-`ContainerElement` - Корневой элемент конфигурации, который загружается из документа.
+`ContainerElement` - Конфигурация контейнера, которая загружается из документа, состоит из директив для `ContainerBuilder`, а также из записей регистрации сервисов.
-Классы заканчивающиеся словом `Builder` используются для применения конфигурации к контейнеру,
-классы заканчивающиеся на `Element` содержат информацию о конфигурации и десериализуются из исходного документа.
+В библиотеки приняты следующие правила именования классов:
+
+- `***Builder` используются для применения конфигурации к контейнеру,
+- `***Element` содержат информацию о конфигурации и десериализуются из исходного документа.
## Структура конфигурации контейнера
-Элемент верхнего уровня всегда `ContainerElemnt`, он используется для хранения набора элеметов, которые распознаются и выполняются `ContainerBuilder`.
+Элемент верхнего уровня всегда `container`, он используется для хранения набора элеметов, которые распознаются и выполняются `ContainerBuilder`.
Все элементы, входящие в контейнер наследуются от абстрактного класса `ContainerItemElement`,
который позволяет получить текущий `ContainerBuilder` и выполнить над ним какие-либо действия.
-Примерами элементов контейнера могут быть
+Основные элементы конфигурации контенейра
- `` - включение конфигурации из указанного места
- `` - добавление пространства имен для поиска типов
- `` - добавление в контейнер регистрации типа ``My.App.MyGenericType`1``
+- `` - фабрика, регистрирует свой тип, а также тип `Foo`
+- `` - сериализованный экземпляр объекта, использует `XmlSerializer` для десериализации
+- `` - значение объекта в виде строки, используется для простых типов
Полный набор элементов, доступных для использования в контейнере определяет схема `ContainerConfigurationSchema`,
разработчик может расширить контейнер совими собственными элементами зарегистрировав их в схеме.
+### register
+
+О
+
+
Например, мы используем компоненту `MyHttpClient` для загрузки данных
```xml
diff --git a/Implab/Diagnostics/ChannelAdvertisementEventArgs.cs b/Implab/Diagnostics/ChannelAdvertisementEventArgs.cs
new file mode 100644
--- /dev/null
+++ b/Implab/Diagnostics/ChannelAdvertisementEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Diagnostics;
+
+namespace Implab.Diagnostics
+{
+ public class ChannelAdvertisementEventArgs : EventArgs {
+ internal ChannelAdvertisementEventArgs(object channelId, TraceSource source) {
+ ChannelId = channelId;
+ Source = source;
+ }
+
+ public object ChannelId { get; private set; }
+
+ public TraceSource Source { get; private set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Implab/Diagnostics/Trace.cs b/Implab/Diagnostics/Trace.cs
--- a/Implab/Diagnostics/Trace.cs
+++ b/Implab/Diagnostics/Trace.cs
@@ -1,4 +1,7 @@
-using System;
+// enable System.Diagnostics trace methods
+#define TRACE
+
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -9,7 +12,21 @@ using System.Threading.Tasks;
namespace Implab.Diagnostics {
public static class Trace {
- public static TraceSource TraceSource { get; } = new TraceSource(typeof(T).Name);
+ static Lazy _traceSource = new Lazy(CreateChannel, LazyThreadSafetyMode.ExecutionAndPublication);
+
+ static int _nextId;
+
+ static TraceSource CreateChannel() {
+ var id = Interlocked.Increment(ref _nextId);
+ return new TraceSource(typeof(T).Name);
+ }
+
+ public static TraceSource TraceSource { get { return _traceSource.Value; } }
+
+ public static IDisposable Subscribe() {
+
+ throw new NotImplementedException();
+ }
#if NETFX_TRACE_BUG
readonly static AsyncLocal