# 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 m_currentOperation = new AsyncLocal(); diff --git a/Implab/Implab.csproj b/Implab/Implab.csproj --- a/Implab/Implab.csproj +++ b/Implab/Implab.csproj @@ -8,7 +8,7 @@ and SharedLock, Trace helpers on top of System.Diagnostics, ObjectPool etc. 2012-2018 Sergey Smirnov - 3.0.10 + 3.0.12 https://hg.implab.org/pub/ImplabNet/file/tip/Implab/license.txt https://implab.org https://hg.implab.org/pub/ImplabNet/ diff --git a/Implab/Messaging/ISession.cs b/Implab/Messaging/ISession.cs deleted file mode 100644 --- a/Implab/Messaging/ISession.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Implab.Messaging { - public interface ISession { - /// - /// Starts message consumers, call this method after all adapters are ready - /// - void Start(); - - /// - /// Stops message consumers - /// - void Stop(); - - } -} \ No newline at end of file