changeset 277:963b17c275be v3

Refactoring Added <array> element to injection parameters Working on registrations of factories
author cin
date Sat, 28 Apr 2018 18:48:09 +0300
parents b4e0f81c7425
children 6691aff01de1
files Implab.Playground/Program.cs Implab.Playground/data/sample.xml Implab.ServiceHost/Unity/AbstractContainerItem.cs Implab.ServiceHost/Unity/AbstractInjectionElement.cs Implab.ServiceHost/Unity/AbstractMemberInjection.cs Implab.ServiceHost/Unity/AbstractRegistration.cs Implab.ServiceHost/Unity/ArrayParameterElement.cs Implab.ServiceHost/Unity/AssemblyElement.cs Implab.ServiceHost/Unity/ConstructorInjectionElement.cs Implab.ServiceHost/Unity/ContainerBuilder.cs Implab.ServiceHost/Unity/ContainerConfigurationSchema.cs Implab.ServiceHost/Unity/ContainerElement.cs Implab.ServiceHost/Unity/ContainerItemElement.cs Implab.ServiceHost/Unity/ContainerLifetimeElement.cs Implab.ServiceHost/Unity/ContextLifetimeElement.cs Implab.ServiceHost/Unity/DefaultParameterElement.cs Implab.ServiceHost/Unity/DependencyParameterElement.cs Implab.ServiceHost/Unity/FactoryAbstractRegistration.cs Implab.ServiceHost/Unity/FactoryInjectionElement.cs Implab.ServiceHost/Unity/FactoryRegistrationBuilder.cs Implab.ServiceHost/Unity/HierarchicalLifetimeElement.cs Implab.ServiceHost/Unity/IDependencyReference.cs Implab.ServiceHost/Unity/IInjectionArray.cs Implab.ServiceHost/Unity/IInjectionParameter.cs Implab.ServiceHost/Unity/ISerializedValue.cs Implab.ServiceHost/Unity/ITextValue.cs Implab.ServiceHost/Unity/IncludeElement.cs Implab.ServiceHost/Unity/InjectionParameterElement.cs Implab.ServiceHost/Unity/InjectionValueBuilder.cs Implab.ServiceHost/Unity/InstanceAbstractRegistration.cs Implab.ServiceHost/Unity/InstanceRegistrationBuilder.cs Implab.ServiceHost/Unity/LifetimeElement.cs Implab.ServiceHost/Unity/MethodInjectionElement.cs Implab.ServiceHost/Unity/NamespaceElement.cs Implab.ServiceHost/Unity/PropertyInjectionElement.cs Implab.ServiceHost/Unity/RegisterElement.cs Implab.ServiceHost/Unity/RegistrationBuilder.cs Implab.ServiceHost/Unity/SerializedElement.cs Implab.ServiceHost/Unity/SerializedParameterElement.cs Implab.ServiceHost/Unity/SimgletonLifetimeElement.cs Implab.ServiceHost/Unity/SingletonLifetimeElement.cs Implab.ServiceHost/Unity/TypeAbstractRegistration.cs Implab.ServiceHost/Unity/TypeReferenceParser.cs Implab.ServiceHost/Unity/TypeRegistrationBuilder.cs Implab.ServiceHost/Unity/TypeResolver.cs Implab.ServiceHost/Unity/ValueElement.cs Implab.ServiceHost/Unity/ValueParameterElement.cs Implab.ServiceHost/Unity/readme.md Implab.ServiceHost/docs/XmlConfiguration.md
diffstat 49 files changed, 511 insertions(+), 340 deletions(-) [+]
line wrap: on
line diff
--- a/Implab.Playground/Program.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.Playground/Program.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.Diagnostics;
 using System.Linq;
 using Implab.Diagnostics;
@@ -22,6 +23,10 @@
 
         public string StringValue { get; set; }
 
+        public void AddRange(Foo[] items) {
+            Console.WriteLine($"AddRange: Foo[]");
+        }
+
     }
 
     public interface IContainer<T> {
@@ -42,30 +47,44 @@
         public void SetInstance(T value) {
             Instance = value;
         }
+
+        public void AddRange(List<T> items) {
+            Console.WriteLine($"AddRange: {typeof(List<T>)}");
+        }
+
+        public void AddRange(T[] items) {
+            Console.WriteLine($"AddRange: T[] ofType {typeof(T[])}");
+        }
     }
 
     public class Program {
 
         static void Main(string[] args) {
+            var listener = new SimpleTraceListener(Console.Out);
+            var source = Trace<TypeResolver>.TraceSource;
+            source.Switch.Level = SourceLevels.All;
+            source.Listeners.Add(listener);
+
             var stopwatch = new Stopwatch();
             stopwatch.Start();
 
             var ctx = new ContainerBuilder();
 
             Console.WriteLine($"Created: {stopwatch.ElapsedMilliseconds}");
-
+            stopwatch.Restart();
+            
             ctx.LoadConfig("data/sample.xml");
 
             Console.WriteLine($"Loaded: {stopwatch.ElapsedMilliseconds}");
 
             var container = ctx.Container;
 
-            
-
+            stopwatch.Restart();
             var instace1 = container.Resolve<IContainer<string>>();
             Console.WriteLine($"Resolved1: {stopwatch.ElapsedMilliseconds}");
+
+            stopwatch.Restart();
             var instace2 = container.Resolve<IContainer<Foo>>();
-
             Console.WriteLine($"Resolved2: {stopwatch.ElapsedMilliseconds}");
 
             DisplayContainerRegistrations(container);
--- a/Implab.Playground/data/sample.xml	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.Playground/data/sample.xml	Sat Apr 28 18:48:09 2018 +0300
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <container xmlns="http://implab.org/schemas/servicehost/unity.v1.xsd">
     <namespace name="System"/>
+    <namespace name="System.Collections.Generic"/>
     <namespace name="Implab.Playground"/>
     
     <!-- foo1 -->
@@ -21,6 +22,11 @@
     </register>
 
     <register type="Foo">
+        <method name="AddRange">
+            <array itemsType="Foo">
+                <dependency name="foo2"/>
+            </array>
+        </method>
     </register>
 
     <register type="IContainer{}" mapTo="Container{}">
@@ -28,6 +34,15 @@
         <method name="SetInstance">
             <dependency type="T"/>
         </method>
+        <method name="AddRange">
+            <array itemsType="T">
+                <dependency name="foo2"/>
+            </array>
+        </method>
+    </register>
+
+    <register type="List{}">
+        <constructor />
     </register>
 
     <register type="IContainer{String}" mapTo="Container{String}">
@@ -46,4 +61,8 @@
     <value name="connection1" type="String"><![CDATA[Connect me <here>!]]></value>
     <value name="name1" type="String" value="Hello!"/>
 
+    <factory name="foo3" type="FooFactory">
+        <parameter name="FooName"><![CDATA[Wired "" objecty <> name @#$%^&]]></parameter>
+    </factory>
+
 </container>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/AbstractContainerItem.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -0,0 +1,12 @@
+namespace Implab.ServiceHost.Unity {
+    
+    /// <summary>
+    /// Базовый класс для элеметов контейнера.
+    /// </summary>
+    /// <remarks>
+    /// XmlSerializer требует использования классов при объявлении свойств, которые будут сериализованы <see cref="ContainerElement.Items"/>
+    /// </remarks>
+    public abstract class AbstractContainerItem {
+        public abstract void Visit(ContainerBuilder builder);
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/AbstractInjectionElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-using System;
-
-namespace Implab.ServiceHost.Unity {
-    /// <summary>
-    /// Base class for injections, each injection is applied to the type registration context.
-    /// </summary>
-    public abstract class AbstractInjectionElement {
-        internal abstract void Visit(TypeRegistrationBuilder context);
-    }
-}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/AbstractMemberInjection.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -0,0 +1,10 @@
+using System;
+
+namespace Implab.ServiceHost.Unity {
+    /// <summary>
+    /// Base class for injections, each injection is applied to the type registration context.
+    /// </summary>
+    public abstract class AbstractMemberInjection {
+        internal abstract void Visit(TypeRegistrationBuilder context);
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/AbstractRegistration.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/AbstractRegistration.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -5,7 +5,10 @@
 
 namespace Implab.ServiceHost.Unity
 {
-    public abstract class AbstractRegistration : ContainerItemElement {
+    /// <summary>
+    /// Базовая информаци о регистрации в контейнере: тип, имя и время жизни
+    /// </summary>
+    public abstract class AbstractRegistration : AbstractContainerItem {
 
         /// <summary>
         /// An optional name for a registration in the container
@@ -15,7 +18,7 @@
             get; set;
         }
 
-        [XmlElement("signleton", typeof(SimgletonLifetimeElement))]
+        [XmlElement("signleton", typeof(SingletonLifetimeElement))]
         [XmlElement("context", typeof(ContextLifetimeElement))]
         [XmlElement("container", typeof(ContainerLifetimeElement))]
         [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
@@ -27,5 +30,13 @@
         [XmlAttribute("type")]
         public string RegistrationType { get; set; }
 
+        public virtual Type GetRegistrationType(Func<string,Type> resolver) {
+            return resolver(RegistrationType);
+        }
+
+        public virtual void Visit(RegistrationBuilder builder) {
+            Lifetime?.Visit(builder);
+        }
+
     }
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/ArrayParameterElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -0,0 +1,20 @@
+using System.Xml.Serialization;
+
+namespace Implab.ServiceHost.Unity
+{
+    public class ArrayParameterElement : InjectionParameterElement {
+
+        [XmlAttribute("itemsType")]
+        public string ItemsType { get; set; }
+
+        [XmlElement("dependency", typeof(DependencyParameterElement))]
+        [XmlElement("value", typeof(ValueParameterElement))]
+        [XmlElement("serialized", typeof(SerializedParameterElement))]
+        [XmlElement("default", typeof(DefaultParameterElement))]
+        public InjectionParameterElement[] Items { get; set; }
+
+        public override void Visit(InjectionValueBuilder builder) {
+            builder.Visit(this);
+        }
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/AssemblyElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/AssemblyElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -3,12 +3,12 @@
 namespace Implab.ServiceHost.Unity
 {
     [XmlRoot("assembly", Namespace = Schema.ContainerConfigurationNamespace)]
-    public class AssemblyElement : ContainerItemElement {
+    public class AssemblyElement : AbstractContainerItem {
         [XmlAttribute("name")]
         public string AssemblyName { get; set; }
         
-        public override void Visit(ContainerBuilder context) {
-            context.Visit(this);
+        public override void Visit(ContainerBuilder builder) {
+            builder.Visit(this);
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ConstructorInjectionElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/ConstructorInjectionElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -1,12 +1,13 @@
 using System.Xml.Serialization;
 
 namespace Implab.ServiceHost.Unity {
-    public class ConstructorInjectionElement : AbstractInjectionElement {
+    public class ConstructorInjectionElement : AbstractMemberInjection {
         
         [XmlElement("dependency", typeof(DependencyParameterElement))]
         [XmlElement("value", typeof(ValueParameterElement))]
         [XmlElement("serialized", typeof(SerializedParameterElement))]
         [XmlElement("default", typeof(DefaultParameterElement))]
+        [XmlElement("array", typeof(ArrayParameterElement))]
         public InjectionParameterElement[] Parameters { get; set; }
 
         internal override void Visit(TypeRegistrationBuilder context) {
--- a/Implab.ServiceHost/Unity/ContainerBuilder.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/ContainerBuilder.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -39,9 +39,10 @@
             return m_resolver.Resolve(typeReference);
         }
 
-        internal void Visit(RegisterElement registerElement) {
-            var registrationType = ResolveType(registerElement.RegistrationType);
-            var implementationType = string.IsNullOrEmpty(registerElement.MapToType) ? registrationType : ResolveType(registerElement.MapToType);
+
+        internal void Visit(TypeAbstractRegistration typeRegistration) {
+            var registrationType = typeRegistration.GetRegistrationType(ResolveType);
+            var implementationType = typeRegistration.GetImplementationType(ResolveType) ?? registrationType;
 
             var registrationContext = new TypeRegistrationBuilder(
                 m_resolver,
@@ -49,46 +50,44 @@
                 implementationType
             );
 
-            if (registerElement.Injectors != null) {
-                foreach (var injector in registerElement.Injectors) {
-                    injector.Visit(registrationContext);
-                }
-            }
+            typeRegistration.Visit(registrationContext);
 
             m_container.RegisterType(
                 registrationContext.RegistrationType,
                 registrationContext.ImplementationType,
-                registerElement.Name,
-                registerElement.Lifetime?.GetLifetimeManager(this),
+                typeRegistration.Name,
+                registrationContext.Lifetime,
                 registrationContext.Injections
             );
         }
 
-        internal void Visit(SerializedElement serializedElement) {
-            var registrationType = ResolveType(serializedElement.RegistrationType);
-            var valueBuilder = new InjectionValueBuilder(m_resolver, null);
+        internal void Visit(InstanceAbstractRegistration instanceRegistration) {
+            var registrationType = instanceRegistration.GetRegistrationType(ResolveType);
+
+            var builder = new InstanceRegistrationBuilder(m_resolver, registrationType);
 
-            valueBuilder.Visit(serializedElement);
-            
+            instanceRegistration.Visit(builder);
+
             m_container.RegisterInstance(
-                registrationType,
-                serializedElement.Name,
-                valueBuilder.Value,
-                serializedElement.Lifetime?.GetLifetimeManager(this)
+                builder.ValueBuilder.ValueType,
+                instanceRegistration.Name,
+                builder.ValueBuilder.Value,
+                builder.Lifetime
             );
         }
 
-        internal void Visit(ValueElement valueElement) {
-            var registrationType = ResolveType(valueElement.RegistrationType);
-            var valueBuilder = new InjectionValueBuilder(m_resolver, null);
+        internal void Visit(FactoryAbstractRegistratrion factoryRgistration) {
+            var registrationType = factoryRgistration.GetRegistrationType(ResolveType);
+
+            var builder = new FactoryRegistrationBuilder(registrationType);
 
-            valueBuilder.Visit(valueElement);
-            
-            m_container.RegisterInstance(
-                registrationType,
-                valueElement.Name,
-                valueBuilder.Value,
-                valueElement.Lifetime?.GetLifetimeManager(this)
+            factoryRgistration.Visit(builder);
+
+            m_container.RegisterType(
+                builder.RegistrationType,
+                factoryRgistration.Name,
+                builder.Lifetime,
+                builder.Factory
             );
         }
 
@@ -111,15 +110,9 @@
 
         public void LoadConfig(string file) {
             var config = m_schema.LoadFile(file);
-            Visit(config);
+            
+            config.Visit(this);
         }
-
-        internal void Visit(ContainerElement containerElement) {
-            foreach (var item in containerElement.Items)
-                item.Visit(this);
-        }
-
-
-
+        
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ContainerConfigurationSchema.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/ContainerConfigurationSchema.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -33,15 +33,15 @@
             Safe.ArgumentNotNull(type, nameof(type));
             Safe.ArgumentNotEmpty(name, nameof(name));
             
-            if(!type.IsSubclassOf(typeof(ContainerItemElement)))
-                throw new Exception($"RegisterContainerElement '{name}': {type} must be subclass of {typeof(ContainerItemElement)}");
+            if(!type.IsSubclassOf(typeof(AbstractContainerItem)))
+                throw new Exception($"RegisterContainerElement '{name}': {type} must be subclass of {typeof(AbstractContainerItem)}");
 
             m_containerItems.XmlElements.Add(
                 new XmlElementAttribute(name, type)
             );
         }
 
-        public void RegisterContainerElement<T>(string name) where T : ContainerItemElement {
+        public void RegisterContainerElement<T>(string name) where T : AbstractContainerItem {
             RegisterContainerElement(typeof(T), name);
         }
 
--- a/Implab.ServiceHost/Unity/ContainerElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/ContainerElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -6,12 +6,14 @@
 
 namespace Implab.ServiceHost.Unity {
     [XmlRoot("container", Namespace = Schema.ContainerConfigurationNamespace)]
-    public class ContainerElement : ContainerItemElement {
+    public class ContainerElement : AbstractContainerItem {
 
-        public List<ContainerItemElement> Items { get; set; } = new List<ContainerItemElement>();
+        public List<AbstractContainerItem> Items { get; set; } = new List<AbstractContainerItem>();
 
         public override void Visit(ContainerBuilder context) {
-            context.Visit(this);
+            if (Items != null)
+                foreach(var item in Items)
+                    item.Visit(context);
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ContainerItemElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-namespace Implab.ServiceHost.Unity {
-    public abstract class ContainerItemElement {
-        public abstract void Visit(ContainerBuilder context);
-    }
-}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ContainerLifetimeElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/ContainerLifetimeElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -3,8 +3,8 @@
 namespace Implab.ServiceHost.Unity
 {
     public class ContainerLifetimeElement : LifetimeElement {
-        public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
-            return new ContainerControlledLifetimeManager();
+        public override void Visit(RegistrationBuilder builder) {
+            builder.Visit(this);
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ContextLifetimeElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/ContextLifetimeElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -3,8 +3,8 @@
 namespace Implab.ServiceHost.Unity
 {
     public class ContextLifetimeElement : LifetimeElement {
-        public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
-            return new PerResolveLifetimeManager();
+        public override void Visit(RegistrationBuilder builder) {
+            builder.Visist(this);
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/DefaultParameterElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/DefaultParameterElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -1,12 +1,13 @@
 namespace Implab.ServiceHost.Unity
 {
-    public class DefaultParameterElement : InjectionParameterElement, ITextValue {
+    public class DefaultParameterElement : InjectionParameterElement {
         public string Value {
             get { return null; }
         }
 
         public override void Visit(InjectionValueBuilder builder) {
-            builder.Visit(this);
+            var type = builder.ResolveInjectedValueType(TypeName);
+            builder.SetValue(type, Safe.CreateDefaultValue(type));
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/DependencyParameterElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/DependencyParameterElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -1,7 +1,7 @@
 using System.Xml.Serialization;
 
 namespace Implab.ServiceHost.Unity {
-    public class DependencyParameterElement : InjectionParameterElement, IDependencyReference {
+    public class DependencyParameterElement : InjectionParameterElement {
 
         [XmlAttribute("name")]
         public string DependencyName { get; set; }
@@ -10,7 +10,8 @@
         public bool Optional { get; set; }
 
         public override  void Visit(InjectionValueBuilder builder) {
-            builder.Visit(this);
+            var type = builder.ResolveInjectedValueType(TypeName);
+            builder.SetDependencyReference(type, DependencyName, Optional);
         }
     }
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/FactoryAbstractRegistration.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -0,0 +1,11 @@
+namespace Implab.ServiceHost.Unity {
+    public class FactoryAbstractRegistratrion : AbstractRegistration {
+        public override void Visit(ContainerBuilder builder) {
+            builder.Visit(this);
+        }
+
+        public virtual void Visit(FactoryRegistrationBuilder builder) {
+            base.Visit(builder);
+        }
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/FactoryInjectionElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-namespace Implab.ServiceHost.Unity {
-    public class FactoryInjectionElement : AbstractInjectionElement {
-        internal override void Visit(TypeRegistrationBuilder context) {
-            
-        }
-    }
-}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/FactoryRegistrationBuilder.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -0,0 +1,36 @@
+using System;
+using Implab.Components;
+using Unity;
+using Unity.Injection;
+using Unity.Registration;
+
+namespace Implab.ServiceHost.Unity
+{
+    public class FactoryRegistrationBuilder : RegistrationBuilder {
+        
+        internal InjectionMember Factory { get; private set; }
+
+        internal FactoryRegistrationBuilder(Type registrationType) : base(registrationType) {
+        }
+
+        public void SetFactoryDelegate(Delegate factory) {
+            Safe.ArgumentNotNull(factory, nameof(factory));
+
+            Factory = new DelegateInjectionFactory(factory);
+        }
+
+        public void SetFactoryDependency<T>(string dependencyName, Func<T, object> factory) {
+            Safe.ArgumentNotNull(factory, nameof(factory));
+
+            Factory = new InjectionFactory((c,t,name) => {
+                var backend = c.Resolve<T>(dependencyName);
+                return factory(backend);
+            });
+        }
+
+        public void SetFactoryDependency<TFac, TObj>(string dependencyName) where TFac : IFactory<TObj> {
+            
+            Factory = new InjectionFactory(c => c.Resolve<TFac>(dependencyName).Create());
+        }
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/HierarchicalLifetimeElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/HierarchicalLifetimeElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -3,8 +3,8 @@
 namespace Implab.ServiceHost.Unity
 {
     public class HierarchicalLifetimeElement : LifetimeElement {
-        public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
-            return new HierarchicalLifetimeManager();
+        public override void Visit(RegistrationBuilder builder) {
+            builder.Visit(this);
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/IDependencyReference.cs	Sat Apr 28 00:11:38 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-namespace Implab.ServiceHost.Unity {
-    public interface IDependencyReference {
-
-        string TypeName { get; }
-
-        bool Optional { get; }
-        
-        string DependencyName { get; }
-    }
-}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/IInjectionArray.cs	Sat Apr 28 00:11:38 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-using System.Collections.Generic;
-
-namespace Implab.ServiceHost.Unity
-{
-    public interface IArrayInjectionParameter {
-
-        string TypeName { get; }
-
-        IEnumerable<IInjectionParameter> Items { get; }
-         
-    }
-}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/IInjectionParameter.cs	Sat Apr 28 00:11:38 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-namespace Implab.ServiceHost.Unity {
-    public interface IInjectionParameter {
-        void Visit(InjectionValueBuilder builder);
-    }
-}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ISerializedValue.cs	Sat Apr 28 00:11:38 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-using System.Xml;
-
-namespace Implab.ServiceHost.Unity {
-    public interface ISerializedValue {
-
-        string TypeName { get; }
-
-        XmlReader GetReader();
-
-    }
-}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ITextValue.cs	Sat Apr 28 00:11:38 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-namespace Implab.ServiceHost.Unity {
-    public interface ITextValue {
-
-        string TypeName { get; }
-
-        string Value { get; }
-
-    }
-}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/IncludeElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/IncludeElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -2,7 +2,7 @@
 
 namespace Implab.ServiceHost.Unity {
     [XmlRoot("include", Namespace = Schema.ContainerConfigurationNamespace)]
-    public class IncludeElement : ContainerItemElement {
+    public class IncludeElement : AbstractContainerItem {
         [XmlAttribute("href")]
         public string Href { get; set; }
 
--- a/Implab.ServiceHost/Unity/InjectionParameterElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/InjectionParameterElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -2,7 +2,7 @@
 using System.Xml.Serialization;
 
 namespace Implab.ServiceHost.Unity {
-    public abstract class InjectionParameterElement : IInjectionParameter {
+    public abstract class InjectionParameterElement {
         
         [XmlAttribute("type")]
         public string TypeName { get; set; }
--- a/Implab.ServiceHost/Unity/InjectionValueBuilder.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/InjectionValueBuilder.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -1,5 +1,7 @@
 using System;
+using System.Collections.Generic;
 using System.ComponentModel;
+using System.Linq;
 using System.Xml.Serialization;
 using Unity.Injection;
 
@@ -11,11 +13,11 @@
 
         public Type DefaultType { get; private set; }
 
-        public Type ValueType { get; set; }
+        public Type ValueType { get; private set; }
 
         public object Value { get; set; }
 
-        public InjectionParameterValue Injection {
+        internal InjectionParameterValue Injection {
             get {
                 if (Value != null)
                     return InjectionParameterValue.ToParameter(Value);
@@ -24,12 +26,12 @@
             }
         }
 
-        internal InjectionValueBuilder(TypeResolver resolver, Type acceptsType) {
+        internal InjectionValueBuilder(TypeResolver resolver, Type defaultType) {
             m_resolver = resolver;
-            DefaultType = acceptsType;
+            DefaultType = defaultType;
         }
 
-        public Type ResolveType(string typeSpec) {
+        public Type ResolveInjectedValueType(string typeSpec) {
             if (string.IsNullOrEmpty(typeSpec)) {
                 if (DefaultType == null)
                     throw new Exception("The type must be specified");
@@ -38,27 +40,50 @@
             return m_resolver.Resolve(typeSpec);
         }
 
-        public void Visit(ITextValue value) {
-            ValueType = ResolveType(value.TypeName);
+        public Type ResolveType(string typeSpec) {
+            return m_resolver.Resolve(typeSpec);
+        }
 
-            Value = string.IsNullOrEmpty(value.Value) ?
-                Safe.CreateDefaultValue(ValueType) :
-                TypeDescriptor.GetConverter(ValueType).ConvertFromString(value.Value);
+        public void SetValue(Type type, object value) {
+            ValueType = type;
+            Value = value;
+        }
+
+        public void SetValue<T>(T value) {
+            SetValue(typeof(T), value);
+        }
+
+        public void SetDependencyReference(Type type, string name, bool optional) {
+            ValueType = type;
+            Value = optional ? (object)new OptionalParameter(type, name) : new ResolvedParameter(type, name);
         }
 
-        public void Visit(ISerializedValue value) {
-            ValueType = ResolveType(value.TypeName);
+        internal void Visit(ArrayParameterElement arrayParameter) {
+            Type itemsType = null;
+            var arrayType = string.IsNullOrEmpty(arrayParameter.TypeName) ? null : ResolveType(arrayParameter.TypeName);
 
-            var serializer = new XmlSerializer(ValueType);
+            if (!string.IsNullOrEmpty(arrayParameter.ItemsType)) {
+                itemsType = ResolveType(arrayParameter.ItemsType);
+                if (arrayType == null)
+                    arrayType = itemsType.MakeArrayType();
+            } else {
+                itemsType = arrayType?.GetInterface(typeof(IEnumerable<>).FullName)?.GetGenericArguments()[0];
+            }
 
-            using (var reader = value.GetReader())
-                Value = new InjectionParameter(ValueType, serializer.Deserialize(reader));
-        }
+            if (itemsType == null)
+                throw new Exception("Failed to determine array elements type");
 
-        public void Visit(IDependencyReference value) {
-            ValueType = ResolveType(value.TypeName);
-            Value = new ResolvedParameter(ValueType, value.DependencyName);
+            InjectionParameterValue[] injections = (arrayParameter.Items ?? new InjectionParameterElement[0])
+                .Select(x => {
+                    var builder = new InjectionValueBuilder(m_resolver, itemsType);
+                    x.Visit(builder);
+                    return builder.Injection;
+                })
+                .ToArray();
+
+            var array = itemsType.IsGenericParameter ? (object)new GenericResolvedArrayParameter(itemsType.Name, injections) : new ResolvedArrayParameter(itemsType, injections);
+            ValueType = arrayType;
+            Value = array;
         }
-
     }
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/InstanceAbstractRegistration.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -0,0 +1,12 @@
+namespace Implab.ServiceHost.Unity
+{
+    public abstract class InstanceAbstractRegistration : AbstractRegistration {
+        public override void Visit(ContainerBuilder builder) {
+            builder.Visit(this);
+        }
+
+        public virtual void Visit(InstanceRegistrationBuilder builder) {
+            base.Visit(builder);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/InstanceRegistrationBuilder.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -0,0 +1,13 @@
+using System;
+
+namespace Implab.ServiceHost.Unity
+{
+    public class InstanceRegistrationBuilder : RegistrationBuilder {
+
+        public InjectionValueBuilder ValueBuilder { get; private set; }
+
+        internal InstanceRegistrationBuilder(TypeResolver typeResolver, Type registrationType) : base(registrationType) {
+            ValueBuilder = new InjectionValueBuilder(typeResolver, registrationType);
+        }
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/LifetimeElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/LifetimeElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -1,10 +1,5 @@
-using Unity.Lifetime;
-
-namespace Implab.ServiceHost.Unity
-{
-    public abstract class LifetimeElement
-    {
-        public abstract LifetimeManager GetLifetimeManager(ContainerBuilder ctx);
-        
+namespace Implab.ServiceHost.Unity {
+    public abstract class LifetimeElement {
+        public abstract void Visit(RegistrationBuilder builder);
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/MethodInjectionElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/MethodInjectionElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -1,7 +1,7 @@
 using System.Xml.Serialization;
 
 namespace Implab.ServiceHost.Unity {
-    public class MethodInjectionElement : AbstractInjectionElement {
+    public class MethodInjectionElement : AbstractMemberInjection {
 
         [XmlAttribute("name")]
         public string Name { get; set; }
@@ -10,6 +10,7 @@
         [XmlElement("value", typeof(ValueParameterElement))]
         [XmlElement("serialized", typeof(SerializedParameterElement))]
         [XmlElement("default", typeof(DefaultParameterElement))]
+        [XmlElement("array", typeof(ArrayParameterElement))]
         public InjectionParameterElement[] Parameters { get; set; }
 
         internal override void Visit(TypeRegistrationBuilder context) {
--- a/Implab.ServiceHost/Unity/NamespaceElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/NamespaceElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -3,7 +3,7 @@
 namespace Implab.ServiceHost.Unity
 {
     [XmlRoot("namespace", Namespace = Schema.ContainerConfigurationNamespace)]
-    public class NamespaceElement : ContainerItemElement {
+    public class NamespaceElement : AbstractContainerItem {
 
         [XmlAttribute("name")]
         public string Name { get; set; }
--- a/Implab.ServiceHost/Unity/PropertyInjectionElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/PropertyInjectionElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -1,7 +1,7 @@
 using System.Xml.Serialization;
 
 namespace Implab.ServiceHost.Unity {
-    public class PropertyInjectionElement : AbstractInjectionElement {
+    public class PropertyInjectionElement : AbstractMemberInjection {
 
         [XmlAttribute("name")]
         public string Name { get; set; }
@@ -10,6 +10,7 @@
         [XmlElement("value", typeof(ValueParameterElement))]
         [XmlElement("serialized", typeof(SerializedParameterElement))]
         [XmlElement("default", typeof(DefaultParameterElement))]
+        [XmlElement("array", typeof(ArrayParameterElement))]
         public InjectionParameterElement Value { get; set; }
 
         internal override void Visit(TypeRegistrationBuilder context) {
--- a/Implab.ServiceHost/Unity/RegisterElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/RegisterElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -6,7 +6,7 @@
 namespace Implab.ServiceHost.Unity {
 
     [XmlRoot("register", Namespace = Schema.ContainerConfigurationNamespace)]
-    public class RegisterElement : AbstractRegistration  {
+    public class RegisterElement : TypeAbstractRegistration  {
         
         /// <summary>
         /// An optional type which is registered as a service in the container, must be assignable to <see cref="ProvidesType">.
@@ -18,11 +18,19 @@
         [XmlElement("constructor", typeof(ConstructorInjectionElement))]
         [XmlElement("property", typeof(PropertyInjectionElement))]
         [XmlElement("method", typeof(MethodInjectionElement))]
-        public AbstractInjectionElement[] Injectors { get; set; }
+        public AbstractMemberInjection[] Injectors { get; set; }
+
+        public override Type GetImplementationType(Func<string, Type> resolver) {
+            return string.IsNullOrEmpty(MapToType) ? null : resolver(MapToType);
+        }
 
-        public override void Visit(ContainerBuilder context) {
-            context.Visit(this);
+        public override void Visit(TypeRegistrationBuilder builder) {
+            if(Injectors != null)
+                foreach(var injector in Injectors)
+                    injector.Visit(builder);
         }
+
+        
     }
     
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/RegistrationBuilder.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/RegistrationBuilder.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -5,17 +5,39 @@
 using System.Xml.Serialization;
 using Implab.Xml;
 using Unity.Injection;
+using Unity.Lifetime;
 using Unity.Registration;
 
 namespace Implab.ServiceHost.Unity {
+    /// <summary>
+    /// Базовый класс для формирования записей в контейнере, созволяет указать время жизни для записи
+    /// </summary>
     public abstract class RegistrationBuilder {
         public Type RegistrationType {
             get;
             private set;
         }
 
+        internal LifetimeManager Lifetime { get; set; }
+
         protected RegistrationBuilder(Type registrationType) {
             RegistrationType = registrationType;
         }
+
+        internal void Visit(SingletonLifetimeElement simgletonLifetime) {
+            Lifetime = new SingletonLifetimeManager();
+        }
+
+        internal void Visit(ContainerLifetimeElement containerLifetime) {
+            Lifetime = new ContainerControlledLifetimeManager();
+        }
+
+        internal void Visit(HierarchicalLifetimeElement hierarchicalLifetime) {
+            Lifetime = new HierarchicalLifetimeManager();
+        }
+
+        internal void Visist(ContextLifetimeElement contextLifetime) {
+            Lifetime = new PerResolveLifetimeManager();
+        }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/SerializedElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/SerializedElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -4,7 +4,7 @@
 
 namespace Implab.ServiceHost.Unity
 {
-    public class SerializedElement : AbstractRegistration, ISerializedValue {
+    public class SerializedElement : InstanceAbstractRegistration {
         [XmlAttribute("href")]
         public string Location { get; set; }
 
@@ -15,29 +15,15 @@
         [XmlAnyElement]
         public XmlElement[] Content { get; set; }
 
-        string ISerializedValue.TypeName {
-            get {
-                return string.IsNullOrEmpty(SerializedType) ? RegistrationType : SerializedType;
-            }
-        }
-
-        public string TypeName => throw new NotImplementedException();
-
-        public override void Visit(ContainerBuilder context) {
-            context.Visit(this);
-        }
+        public override void Visit(InstanceRegistrationBuilder builder) {
+            base.Visit(builder);
 
-        public XmlReader GetReader() {
-            if (!string.IsNullOrEmpty(Location))
-                return XmlReader.Create(Location);
-            if (Content != null && Content.Length > 0)
-                return Content[0].CreateNavigator().ReadSubtree();
-
-            throw new Exception("No content found, expected XML document");
-        }
-
-        public void Visit(InjectionValueBuilder builder) {
-            throw new NotImplementedException();
+            var parameter = new SerializedParameterElement {
+                TypeName = SerializedType,
+                Location = Location,
+                Content = Content
+            };
+            parameter.Visit(builder.ValueBuilder);
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/SerializedParameterElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/SerializedParameterElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -5,7 +5,7 @@
 
 namespace Implab.ServiceHost.Unity
 {
-    public class SerializedParameterElement : InjectionParameterElement, ISerializedValue {
+    public class SerializedParameterElement : InjectionParameterElement {
         [XmlAttribute("href")]
         public string Location { get; set; }
 
@@ -22,7 +22,12 @@
         }
 
         public override void Visit(InjectionValueBuilder builder) {
-            builder.Visit(this);
+            var type = builder.ResolveInjectedValueType(TypeName);
+
+            var serializer = new XmlSerializer(type);
+            using(var reader = GetReader())
+                builder.SetValue(type, serializer.Deserialize(reader));
+            
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/SimgletonLifetimeElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-using Unity.Lifetime;
-
-namespace Implab.ServiceHost.Unity
-{
-    public class SimgletonLifetimeElement : LifetimeElement {
-        public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
-            return new SingletonLifetimeManager();
-        }
-    }
-}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/SingletonLifetimeElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -0,0 +1,8 @@
+namespace Implab.ServiceHost.Unity
+{
+    public class SingletonLifetimeElement : LifetimeElement {
+        public override void Visit(RegistrationBuilder builder) {
+            builder.Visit(this);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/TypeAbstractRegistration.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -0,0 +1,17 @@
+using System;
+
+namespace Implab.ServiceHost.Unity
+{
+    public abstract class TypeAbstractRegistration : AbstractRegistration {
+
+        public abstract Type GetImplementationType(Func<string,Type> resolver);
+        
+        override public void Visit(ContainerBuilder builder)  {
+            builder.Visit(this);
+        }
+
+        public virtual void Visit(TypeRegistrationBuilder builder) {
+            base.Visit(builder);
+        }
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/TypeReferenceParser.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/TypeReferenceParser.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -17,10 +17,14 @@
 
             CloseList,
 
+            OpenArray,
+
+            CloseArray,
+
             Eof
         }
 
-        readonly Regex _tokens = new Regex(@"([\w\+]+)|\s*([\.{},])\s*");
+        readonly Regex _tokens = new Regex(@"([\w\+]+)|\s*([\.{},\[\]])\s*");
 
         TokenType m_token;
 
@@ -73,6 +77,12 @@
                         case ",":
                             m_token = TokenType.Comma;
                             break;
+                        case "[":
+                            m_token = TokenType.OpenArray;
+                            break;
+                        case "]":
+                            m_token = TokenType.CloseArray;
+                            break;
                     }
                 }
                 return true;
@@ -82,7 +92,7 @@
 
         public TypeReference Parse() {
             var result = ReadTypeReference();
-            if (ReadToken())
+            if (Token != TokenType.Eof)
                 ThrowUnexpectedToken();
             return result;
         }
@@ -142,6 +152,10 @@
             return typeReference;
         }
 
+        int CountDimentions() {
+            return 0;
+        }
+
         TypeReference[] ReadTypeReferenceList() {
             var list = new List<TypeReference>();
 
--- a/Implab.ServiceHost/Unity/TypeRegistrationBuilder.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/TypeRegistrationBuilder.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -11,7 +11,7 @@
 
         readonly List<InjectionMember> m_injections = new List<InjectionMember>();
 
-        public InjectionMember[] Injections { get { return m_injections.ToArray(); } }
+        internal InjectionMember[] Injections { get { return m_injections.ToArray(); } }
 
         public Type ImplementationType {
             get;
--- a/Implab.ServiceHost/Unity/TypeResolver.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/TypeResolver.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -5,11 +5,9 @@
 using System.Text.RegularExpressions;
 using Implab.Diagnostics;
 
-namespace Implab.ServiceHost.Unity
-{
+namespace Implab.ServiceHost.Unity {
     using static Trace<TypeResolver>;
-    public class TypeResolver
-    {
+    public class TypeResolver {
         readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>();
 
         Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
@@ -49,7 +47,7 @@
             var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0;
 
             Type resolved;
-            if(!m_cache.TryGetValue(reference.ToString(), out resolved)) {
+            if (!m_cache.TryGetValue(reference.ToString(), out resolved)) {
                 resolved = ResolveInternal(reference, args, argc);
                 if (resolved == null)
                     throw new Exception($"Failed to resolve {reference}");
@@ -65,7 +63,7 @@
 
         Type ResolveInternal(TypeReference reference, Type[] args, int argc) {
             var resolved = ProbeInNamespaces(
-                String.Join(".", new [] { reference.Namespace, reference.TypeName }.Where(x => !string.IsNullOrEmpty(x)) ),
+                String.Join(".", new[] { reference.Namespace, reference.TypeName }.Where(x => !string.IsNullOrEmpty(x))),
                 args,
                 argc,
                 reference.IsArray,
@@ -73,17 +71,24 @@
             );
 
             if (resolved == null && m_parent != null)
-                resolved = m_parent.Resolve(reference);
-            
+                resolved = m_parent.ResolveInternal(reference, args, argc);
+
             return resolved;
         }
 
         public Type ProbeInNamespaces(string localName, Type[] args, int argc, bool isArray, string referenceName) {
             foreach (var ns in m_namespases) {
-                var typeName = FormatName(new [] { ns, localName}, argc, args, isArray);
+                var typeName = FormatName(new[] { ns, localName }, argc);
 
                 var resolved = Probe(typeName);
                 if (resolved != null) {
+                    if (args != null && args.Length > 0) {
+                        resolved = resolved.MakeGenericType(args);
+                    }
+
+                    if (isArray)
+                        resolved = resolved.MakeArrayType();
+
                     Log("Probe succeed {0} in '{1}': {2} -> {3}", referenceName, ns, typeName, resolved.AssemblyQualifiedName);
                     return resolved;
                 } else {
@@ -97,7 +102,7 @@
         Type Probe(string typeName) {
             var assemblies = AppDomain.CurrentDomain.GetAssemblies();
 
-            foreach(var assembly in assemblies) {
+            foreach (var assembly in assemblies) {
                 var type = assembly.GetType(typeName);
                 if (type != null)
                     return type;
@@ -105,25 +110,16 @@
             return null;
         }
 
-        string FormatName(string[] parts, int argc, Type[] args, bool isArray) {
+        string FormatName(string[] parts, int argc) {
             var builder = new StringBuilder();
-            
+
             builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x))));
             if (argc > 0) {
                 builder.Append('`');
                 builder.Append(argc);
             }
 
-            if (args!= null && args.Length > 0) {
-                builder.Append('[');
-                builder.Append(string.Join(",", args.Select(x => $"[{x.AssemblyQualifiedName}]")));
-                builder.Append(']');
-            }
-
-            if(isArray)
-                builder.Append("[]");
-
-                return builder.ToString();
+            return builder.ToString();
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ValueElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/ValueElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -1,7 +1,7 @@
 using System.Xml.Serialization;
 
 namespace Implab.ServiceHost.Unity {
-    public class ValueElement : AbstractRegistration, ITextValue {
+    public class ValueElement : InstanceAbstractRegistration {
         
         [XmlAttribute("value")]
         public string Value { get; set; }
@@ -9,10 +9,8 @@
         [XmlText]
         public string Text { get; set; }
 
-        string ITextValue.Value {
-            get {
-                return string.IsNullOrEmpty(Value) ? Text : Value;
-            }
+        string GetTextValue() {
+            return string.IsNullOrEmpty(Value) ? Text : Value;
         }
 
         public string TypeName {
@@ -21,8 +19,13 @@
             }
         }
 
-        public override void Visit(ContainerBuilder context) {
-            context.Visit(this);
+        public override void Visit(InstanceRegistrationBuilder builder) {
+            base.Visit(builder);
+            var parameter = new ValueParameterElement {
+                Value = Value,
+                Text = Text
+            };
+            parameter.Visit(builder.ValueBuilder);
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ValueParameterElement.cs	Sat Apr 28 00:11:38 2018 +0300
+++ b/Implab.ServiceHost/Unity/ValueParameterElement.cs	Sat Apr 28 18:48:09 2018 +0300
@@ -1,13 +1,21 @@
+using System.ComponentModel;
 using System.Xml.Serialization;
 
 namespace Implab.ServiceHost.Unity {
-    public class ValueParameterElement : InjectionParameterElement, ITextValue {
-        [XmlText]
+    public class ValueParameterElement : InjectionParameterElement {
         [XmlAttribute("value")]
         public string Value { get; set; }
 
+        [XmlText]
+        public string Text { get; set; }
+
+        string GetTextValue() {
+            return string.IsNullOrEmpty(Value) ? Text : Value;
+        }
+
         public override void Visit(InjectionValueBuilder builder) {
-            builder.Visit(this);
+            var type = builder.ResolveInjectedValueType(TypeName);
+            builder.SetValue(type, TypeDescriptor.GetConverter(type).ConvertFromString(GetTextValue()));
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/readme.md	Sat Apr 28 00:11:38 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-# XML Конфигурация IoC контейнера
-
-Данная библиоетка создавалась для загрузки и применения конфигурации к IoC контейнеру, она не предназначена для конфигурирования
-контейнера во время выполнения, большинство контейнеров уже обладают данным функционалом.
-
-На данный момент поддерживается единственный вид контейнера - [Unity Container](https://unitycontainer.github.io/)
-
-Unity уже обладает средствами загрузки конфигурации из XML, данная библиотека позволяет решать следующие задачи
-
-- Конфигурация является простым Xml документом, который можно получить из любого источика и не ограничивается `.config` файлами приложения
-- Включение существующе конфигурации `<include href='config.xml'/>` в текущую
-- Поддержка сериализованных объектов в качестве регистраций сервисов и параметров
-- Описание зависимостей может быть расширено собсвтенными элементами с произвольной структурой
-- Поддержка специфиакции генериков любой вложенности `Dictionary{Foo,Bar{Int32}}`
-
-## Общая архитектура
-
-`Implab.ServiceHost.Unity` содержит в себе классы для загрузки и применения XML конфигурации к IoC контейнеру, в частности к Unity.
-
-1. Настраивается схема `ContainerConfigurationSchema`
-2. Загружается документ и десереализуется в виде `ContainerElement`
-3. Создается `ContainerBuilder` при помощи которого применяются настройки из `ContainerElement`
-
-`ContainerConfigurationSchema` - определяет элементы которые могут быть использованы в конфигурации контейнера, предоставляет настроенный `XmlSerializer`.
-
-`ContainerBuilder` - основной класс, который используется для применения конфигурации к контейнеру, добавляет записи регистрации сервисов.
-
-`ContainerElement` - Корневой элемент конфигурации, который загружается из документа.
-
-Классы заканчивающиеся словом `Builder` используются для применения конфигурации к контейнеру,
-классы заканчивающиеся на `Element` содержат информацию о конфигурации и десериализуются из исходного документа.
-
-## Структура конфигурации контейнера
-
-Элемент верхнего уровня всегда `ContainerElemnt`, он используется для хранения набора элеметов, которые распознаются и выполняются `ContainerBuilder`.
-
-Все элементы, входящие в контейнер наследуются от абстрактного класса `ContainerItemElement`,
-который позволяет получить текущий `ContainerBuilder` и выполнить над ним какие-либо действия.
-
-Примерами элементов контейнера могут быть
-
-- `<include href='config.xml'/>` - включение конфигурации из указанного места
-- `<namespace name='My.App'/>` - добавление пространства имен для поиска типов
-- `<register type='MyGenericType{}'/>` - добавление в контейнер регистрации типа ``My.App.MyGenericType`1``
-
-Полный набор элементов, доступных для использования в контейнере определяет схема `ContainerConfigurationSchema`,
-разработчик может расширить контейнер совими собственными элементами зарегистрировав их в схеме.
-
-Например, мы используем компоненту `MyHttpClient` для загрузки данных
-
-```xml
-    <register type="IClient" mapTo="MyHttpClient">
-        <property name="proxy">
-            <value>socks5://proxy1.my.company</value>
-        </property>
-    </register>
-```
-
-При частом использовании можно сделать описание конфигурации несколько проще,
-описав новый эелемент конфигурации
-
-```csharp
-public class MyHttpClientElement : ContainerItemElement {
-
-    public string Proxy { get; set; }
-
-    public override void Visit(ContainerBuilder builder) {
-        // создаем описание элемента
-        var registration = new RegistrationElement {
-            RegistrationType = "IClient",
-            ImplementationType = "My.App.MyHttpClient",
-            Injectors = new [] {
-                new PropertyInjectionElement {
-                    Name = "Proxy",
-                    Value = ValueParameterElement {
-                        Value = Proxy
-                    }
-                }
-            }
-        };
-
-        // применяем созданное описание к контейнеру
-        builder.Visit(registration)
-    }
-}
-```
-
-Регистрируем новый элемент в схеме
-
-```csharp
-schema.RegisterContainerElement<MyHttpClientElement>("http");
-```
-
-Используем новый элемент в конфигурации
-
-```xml
-    <http>
-        <proxy>socks5://proxy1.my.company</propxy>
-    </http>
-```
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/docs/XmlConfiguration.md	Sat Apr 28 18:48:09 2018 +0300
@@ -0,0 +1,100 @@
+# XML Конфигурация IoC контейнера
+
+Данная библиоетка создавалась для загрузки и применения конфигурации к IoC контейнеру, она не предназначена для конфигурирования
+контейнера во время выполнения, большинство контейнеров уже обладают данным функционалом.
+
+На данный момент поддерживается единственный вид контейнера - [Unity Container](https://unitycontainer.github.io/)
+
+Unity уже обладает средствами загрузки конфигурации из XML, данная библиотека позволяет решать следующие задачи
+
+- Конфигурация является простым Xml документом, который можно получить из любого источика и не ограничивается `.config` файлами приложения
+- Включение существующе конфигурации `<include href='config.xml'/>` в текущую
+- Поддержка сериализованных объектов в качестве регистраций сервисов и параметров
+- Описание зависимостей может быть расширено собсвтенными элементами с произвольной структурой
+- Поддержка специфиакции генериков любой вложенности `Dictionary{Foo,Bar{Int32}}`
+
+## Общая архитектура
+
+`Implab.ServiceHost.Unity` содержит в себе классы для загрузки и применения XML конфигурации к IoC контейнеру, в частности к Unity.
+
+1. Настраивается схема `ContainerConfigurationSchema`
+2. Загружается документ и десереализуется в виде `ContainerElement`
+3. Создается `ContainerBuilder` при помощи которого применяются настройки из `ContainerElement`
+
+`ContainerConfigurationSchema` - определяет элементы которые могут быть использованы в конфигурации контейнера, предоставляет настроенный `XmlSerializer`.
+
+`ContainerBuilder` - основной класс, который используется для применения конфигурации к контейнеру, добавляет записи регистрации сервисов.
+
+`ContainerElement` - Корневой элемент конфигурации, который загружается из документа.
+
+Классы заканчивающиеся словом `Builder` используются для применения конфигурации к контейнеру,
+классы заканчивающиеся на `Element` содержат информацию о конфигурации и десериализуются из исходного документа.
+
+## Структура конфигурации контейнера
+
+Элемент верхнего уровня всегда `ContainerElemnt`, он используется для хранения набора элеметов, которые распознаются и выполняются `ContainerBuilder`.
+
+Все элементы, входящие в контейнер наследуются от абстрактного класса `ContainerItemElement`,
+который позволяет получить текущий `ContainerBuilder` и выполнить над ним какие-либо действия.
+
+Примерами элементов контейнера могут быть
+
+- `<include href='config.xml'/>` - включение конфигурации из указанного места
+- `<namespace name='My.App'/>` - добавление пространства имен для поиска типов
+- `<register type='MyGenericType{}'/>` - добавление в контейнер регистрации типа ``My.App.MyGenericType`1``
+
+Полный набор элементов, доступных для использования в контейнере определяет схема `ContainerConfigurationSchema`,
+разработчик может расширить контейнер совими собственными элементами зарегистрировав их в схеме.
+
+Например, мы используем компоненту `MyHttpClient` для загрузки данных
+
+```xml
+    <register type="IClient" mapTo="MyHttpClient">
+        <property name="proxy">
+            <value>socks5://proxy1.my.company</value>
+        </property>
+    </register>
+```
+
+При частом использовании можно сделать описание конфигурации несколько проще,
+описав новый эелемент конфигурации
+
+```csharp
+public class MyHttpClientElement : ContainerItemElement {
+
+    public string Proxy { get; set; }
+
+    public override void Visit(ContainerBuilder builder) {
+        // создаем описание элемента
+        var registration = new RegistrationElement {
+            RegistrationType = "IClient",
+            ImplementationType = "My.App.MyHttpClient",
+            Injectors = new [] {
+                new PropertyInjectionElement {
+                    Name = "Proxy",
+                    Value = ValueParameterElement {
+                        Value = Proxy
+                    }
+                }
+            }
+        };
+
+        // применяем созданное описание к контейнеру
+        builder.Visit(registration)
+    }
+}
+```
+
+Регистрируем новый элемент в схеме
+
+```csharp
+schema.RegisterContainerElement<MyHttpClientElement>("http");
+```
+
+Используем новый элемент в конфигурации
+
+```xml
+    <http>
+        <proxy>socks5://proxy1.my.company</propxy>
+    </http>
+```
\ No newline at end of file