changeset 274:22629bf26121 v3

Unity xml configuration, alpha2
author cin
date Fri, 27 Apr 2018 04:47:52 +0300
parents 79110a16cab7
children 6fefd5811b9b
files Implab.Playground/Program.cs Implab.Playground/data/sample.xml Implab.ServiceHost/Unity/AbstractInjectionElement.cs Implab.ServiceHost/Unity/AbstractRegistration.cs Implab.ServiceHost/Unity/AssemblyElement.cs Implab.ServiceHost/Unity/ConstructorInjectionElement.cs Implab.ServiceHost/Unity/ContainerBuilder.cs Implab.ServiceHost/Unity/ContainerConfigurationSchema.cs Implab.ServiceHost/Unity/ContainerContext.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/FactoryInjectionElement.cs Implab.ServiceHost/Unity/HierarchicalLifetimeElement.cs Implab.ServiceHost/Unity/IDependencyReference.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/InjectionValueContext.cs Implab.ServiceHost/Unity/InstanceRegistrationContext.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/RegistrationContext.cs Implab.ServiceHost/Unity/SerializedElement.cs Implab.ServiceHost/Unity/SerializedParameterElement.cs Implab.ServiceHost/Unity/SimgletonLifetimeElement.cs Implab.ServiceHost/Unity/TypeRegistrationBuilder.cs Implab.ServiceHost/Unity/TypeRegistrationContext.cs Implab.ServiceHost/Unity/ValueElement.cs Implab.ServiceHost/Unity/ValueParameterElement.cs
diffstat 39 files changed, 394 insertions(+), 327 deletions(-) [+]
line wrap: on
line diff
--- a/Implab.Playground/Program.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.Playground/Program.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -50,7 +50,7 @@
             var stopwatch = new Stopwatch();
             stopwatch.Start();
 
-            var ctx = new ContainerContext();
+            var ctx = new ContainerBuilder();
 
             Console.WriteLine($"Created: {stopwatch.ElapsedMilliseconds}");
 
--- a/Implab.Playground/data/sample.xml	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.Playground/data/sample.xml	Fri Apr 27 04:47:52 2018 +0300
@@ -38,7 +38,7 @@
     </register>
 
     <serialized type="Foo+Bar">
-        <Bar id="1">
+        <Bar xmlns="" id="1">
             <Name>Baaar</Name>
         </Bar>
     </serialized>
--- a/Implab.ServiceHost/Unity/AbstractInjectionElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/AbstractInjectionElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -1,8 +1,10 @@
 using System;
 
-namespace Implab.ServiceHost.Unity
-{
+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(TypeRegistrationContext context);
+        internal abstract void Visit(TypeRegistrationBuilder context);
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/AbstractRegistration.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/AbstractRegistration.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -27,9 +27,5 @@
         [XmlAttribute("type")]
         public string RegistrationType { get; set; }
 
-        public virtual Type ResolveRegistrationType(ContainerContext ctx) {
-            return ctx.Resolve(RegistrationType);
-        }
-
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/AssemblyElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/AssemblyElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -7,7 +7,7 @@
         [XmlAttribute("name")]
         public string AssemblyName { get; set; }
         
-        public override void Visit(ContainerContext context) {
+        public override void Visit(ContainerBuilder context) {
             context.Visit(this);
         }
     }
--- a/Implab.ServiceHost/Unity/ConstructorInjectionElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/ConstructorInjectionElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -9,7 +9,7 @@
         [XmlElement("default", typeof(DefaultParameterElement))]
         public InjectionParameterElement[] Parameters { get; set; }
 
-        internal override void Visit(TypeRegistrationContext context) {
+        internal override void Visit(TypeRegistrationBuilder context) {
             context.Visit(this);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/ContainerBuilder.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using Implab.Diagnostics;
+
+namespace Implab.ServiceHost.Unity {
+    using System.Linq;
+    using System.Reflection;
+    using System.Text;
+    using global::Unity;
+    using global::Unity.Registration;
+    using Implab.Xml;
+    using static Trace<ContainerBuilder>;
+
+    public class ContainerBuilder {
+
+        readonly TypeResolver m_resolver;
+
+        readonly UnityContainer m_container;
+
+        readonly ContainerConfigurationSchema m_schema;
+
+        public UnityContainer Container {
+            get {
+                return m_container;
+            }
+        }
+
+        public ContainerBuilder() : this(null, null) {
+        }
+
+        public ContainerBuilder(UnityContainer container, ContainerConfigurationSchema schema) {
+            m_container = container ?? new UnityContainer();
+            m_resolver = new TypeResolver();
+            m_schema = schema ?? ContainerConfigurationSchema.Default;
+        }
+
+        public Type ResolveType(string typeReference) {
+            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);
+
+            var registrationContext = new TypeRegistrationBuilder(
+                m_resolver,
+                registrationType,
+                implementationType
+            );
+
+            if (registerElement.Injectors != null) {
+                foreach (var injector in registerElement.Injectors) {
+                    injector.Visit(registrationContext);
+                }
+            }
+
+            m_container.RegisterType(
+                registrationContext.RegistrationType,
+                registrationContext.ImplementationType,
+                registerElement.Name,
+                registerElement.Lifetime?.GetLifetimeManager(this),
+                registrationContext.Injections
+            );
+        }
+
+        internal void Visit(SerializedElement serializedElement) {
+            var registrationType = ResolveType(serializedElement.RegistrationType);
+            var valueBuilder = new InjectionValueBuilder(m_resolver, null);
+
+            valueBuilder.Visit(serializedElement);
+            
+            m_container.RegisterInstance(
+                registrationType,
+                serializedElement.Name,
+                valueBuilder.Value,
+                serializedElement.Lifetime?.GetLifetimeManager(this)
+            );
+        }
+
+        internal void Visit(ValueElement valueElement) {
+            var registrationType = ResolveType(valueElement.RegistrationType);
+            var valueBuilder = new InjectionValueBuilder(m_resolver, null);
+
+            valueBuilder.Visit(valueElement);
+            
+            m_container.RegisterInstance(
+                registrationType,
+                valueElement.Name,
+                valueBuilder.Value,
+                valueElement.Lifetime?.GetLifetimeManager(this)
+            );
+        }
+
+        internal void Visit(NamespaceElement namespaceElement) {
+            m_resolver.AddNamespace(namespaceElement.Name);
+        }
+
+        internal void Visit(AssemblyElement assemblyElement) {
+            Assembly.Load(assemblyElement.AssemblyName);
+        }
+
+        internal void Visit(IncludeElement includeElement) {
+            Include(includeElement.Href);
+        }
+
+        public void Include(string file) {
+            var includeContext = new ContainerBuilder(m_container, m_schema);
+            includeContext.LoadConfig(file);
+        }
+
+        public void LoadConfig(string file) {
+            var config = m_schema.LoadFile(file);
+            Visit(config);
+        }
+
+        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	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/ContainerConfigurationSchema.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -55,6 +55,8 @@
             var schema = new ContainerConfigurationSchema();
 
             schema.RegisterContainerElement<RegisterElement>("register");
+            schema.RegisterContainerElement<SerializedElement>("serialized");
+            schema.RegisterContainerElement<ValueElement>("value");
             schema.RegisterContainerElement<IncludeElement>("include");
             schema.RegisterContainerElement<AssemblyElement>("assembly");
             schema.RegisterContainerElement<NamespaceElement>("namespace");
--- a/Implab.ServiceHost/Unity/ContainerContext.cs	Thu Apr 26 19:35:01 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text.RegularExpressions;
-using Implab.Diagnostics;
-
-namespace Implab.ServiceHost.Unity {
-    using System.Linq;
-    using System.Reflection;
-    using System.Text;
-    using global::Unity;
-    using global::Unity.Registration;
-    using Implab.Xml;
-    using static Trace<ContainerContext>;
-
-    public class ContainerContext {
-
-        readonly TypeResolver m_resolver;
-
-        readonly UnityContainer m_container;
-
-        readonly ContainerConfigurationSchema m_schema;
-
-        public UnityContainer Container {
-            get {
-                return m_container;
-            }
-        }
-
-        public ContainerContext() : this(null, null) {
-        }
-
-        public ContainerContext(UnityContainer container, ContainerConfigurationSchema schema) {
-            m_container = container ?? new UnityContainer();
-            m_resolver = new TypeResolver();
-            m_schema = schema ?? ContainerConfigurationSchema.Default;
-        }
-
-        public Type Resolve(string typeReference) {
-            return m_resolver.Resolve(typeReference);
-        }
-
-        internal void Visit(RegisterElement registerElement) {
-            var registrationContext = new TypeRegistrationContext(
-                m_resolver,
-                registerElement.ResolveRegistrationType(this),
-                registerElement.ResolveImplementationType(this)
-            );
-
-            if (registerElement.Injectors != null) {
-                foreach (var injector in registerElement.Injectors) {
-                    injector.Visit(registrationContext);
-                }
-            }
-
-            m_container.RegisterType(
-                registrationContext.RegistrationType,
-                registrationContext.ImplementationType,
-                registerElement.Name,
-                registerElement.Lifetime?.GetLifetimeManager(this),
-                registrationContext.Injections
-            );
-        }
-
-        internal void Visit(SerializedElement serializedElement) {
-            var registrationType = serializedElement.ResolveRegistrationType(this);
-            var instace = serializedElement.GetValue(this);
-
-
-            m_container.RegisterInstance(
-                registrationType,
-                serializedElement.Name,
-                instace,
-                serializedElement.Lifetime?.GetLifetimeManager(this)
-            );
-        }
-
-        internal void Visit(ValueElement valueElement) {
-
-        }
-
-        internal void Visit(NamespaceElement namespaceElement) {
-            m_resolver.AddNamespace(namespaceElement.Name);
-        }
-
-        internal void Visit(AssemblyElement assemblyElement) {
-            Assembly.Load(assemblyElement.AssemblyName);
-        }
-
-        internal void Visit(IncludeElement includeElement) {
-            Include(includeElement.Href);
-        }
-
-        public void Include(string file) {
-            var includeContext = new ContainerContext(m_container, m_schema);
-            includeContext.LoadConfig(file);
-        }
-
-        public void LoadConfig(string file) {
-            var config = m_schema.LoadFile(file);
-            Visit(config);
-        }
-
-        internal void Visit(ContainerElement containerElement) {
-            foreach (var item in containerElement.Items)
-                item.Visit(this);
-        }
-
-
-
-    }
-}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ContainerElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/ContainerElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -8,9 +8,9 @@
     [XmlRoot("container", Namespace = Schema.ContainerConfigurationNamespace)]
     public class ContainerElement : ContainerItemElement {
 
-        public List<ContainerItemElement> Items {get; set; } = new List<ContainerItemElement>();
+        public List<ContainerItemElement> Items { get; set; } = new List<ContainerItemElement>();
 
-        public override void Visit(ContainerContext context) {
+        public override void Visit(ContainerBuilder context) {
             context.Visit(this);
         }
     }
--- a/Implab.ServiceHost/Unity/ContainerItemElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/ContainerItemElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -1,5 +1,5 @@
 namespace Implab.ServiceHost.Unity {
     public abstract class ContainerItemElement {
-        public abstract void Visit(ContainerContext context);
+        public abstract void Visit(ContainerBuilder context);
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ContainerLifetimeElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/ContainerLifetimeElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -3,7 +3,7 @@
 namespace Implab.ServiceHost.Unity
 {
     public class ContainerLifetimeElement : LifetimeElement {
-        public override LifetimeManager GetLifetimeManager(ContainerContext ctx) {
+        public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
             return new ContainerControlledLifetimeManager();
         }
     }
--- a/Implab.ServiceHost/Unity/ContextLifetimeElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/ContextLifetimeElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -3,7 +3,7 @@
 namespace Implab.ServiceHost.Unity
 {
     public class ContextLifetimeElement : LifetimeElement {
-        public override LifetimeManager GetLifetimeManager(ContainerContext ctx) {
+        public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
             return new PerResolveLifetimeManager();
         }
     }
--- a/Implab.ServiceHost/Unity/DefaultParameterElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/DefaultParameterElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -1,9 +1,12 @@
 namespace Implab.ServiceHost.Unity
 {
-    public class DefaultParameterElement : InjectionParameterElement {
-        internal override object Resolve(InjectionValueContext context) {
-            var type = context.ResolveType(TypeName);
-            return Safe.CreateDefaultValue(type);
+    public class DefaultParameterElement : InjectionParameterElement, ITextValue {
+        public string Value {
+            get { return null; }
+        }
+
+        internal override void Visit(InjectionValueBuilder builder) {
+            builder.Visit(this);
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/DependencyParameterElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/DependencyParameterElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -1,12 +1,16 @@
 using System.Xml.Serialization;
 
 namespace Implab.ServiceHost.Unity {
-    public class DependencyParameterElement : InjectionParameterElement {
+    public class DependencyParameterElement : InjectionParameterElement, IDependencyReference {
 
         [XmlAttribute("name")]
         public string DependencyName { get; set; }
 
         [XmlAttribute("optional")]
         public bool Optional { get; set; }
+
+        internal override void Visit(InjectionValueBuilder builder) {
+            builder.Visit(this);
+        }
     }
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/FactoryInjectionElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -0,0 +1,7 @@
+namespace Implab.ServiceHost.Unity {
+    public class FactoryInjectionElement : AbstractInjectionElement {
+        internal override void Visit(TypeRegistrationBuilder context) {
+            
+        }
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/HierarchicalLifetimeElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/HierarchicalLifetimeElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -3,7 +3,7 @@
 namespace Implab.ServiceHost.Unity
 {
     public class HierarchicalLifetimeElement : LifetimeElement {
-        public override LifetimeManager GetLifetimeManager(ContainerContext ctx) {
+        public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
             return new HierarchicalLifetimeManager();
         }
     }
--- a/Implab.ServiceHost/Unity/IDependencyReference.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/IDependencyReference.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -1,5 +1,8 @@
 namespace Implab.ServiceHost.Unity {
     public interface IDependencyReference {
-        string Name { get; set; }
+
+        string TypeName { get; set; }
+        
+        string DependencyName { get; set; }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ISerializedValue.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/ISerializedValue.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -1,7 +1,11 @@
-namespace Implab.ServiceHost.Unity
-{
-    public class ISerializedValue
-    {
-        
+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	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/ITextValue.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -1,5 +1,7 @@
 namespace Implab.ServiceHost.Unity {
     public interface ITextValue {
+        string TypeName { get; }
+
         string Value { get; }
 
     }
--- a/Implab.ServiceHost/Unity/IncludeElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/IncludeElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -6,7 +6,7 @@
         [XmlAttribute("href")]
         public string Href { get; set; }
 
-        public override void Visit(ContainerContext context) {
+        public override void Visit(ContainerBuilder context) {
             context.Visit(this);
         }
     }
--- a/Implab.ServiceHost/Unity/InjectionParameterElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/InjectionParameterElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -7,10 +7,6 @@
         [XmlAttribute("type")]
         public string TypeName { get; set; }
 
-        internal abstract object Resolve(InjectionValueContext context);
-
-        public virtual Type ResolveParameterType(InjectionValueContext context) {
-            return context.ResolveType(TypeName);
-        }
+        internal abstract void Visit(InjectionValueBuilder builder);
     }
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/InjectionValueBuilder.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -0,0 +1,64 @@
+using System;
+using System.ComponentModel;
+using System.Xml.Serialization;
+using Unity.Injection;
+
+namespace Implab.ServiceHost.Unity {
+
+    public class InjectionValueBuilder {
+
+        readonly TypeResolver m_resolver;
+
+        public Type DefaultType { get; private set; }
+
+        public Type ValueType { get; set; }
+
+        public object Value { get; set; }
+
+        public InjectionParameterValue Injection {
+            get {
+                if (Value != null)
+                    return InjectionParameterValue.ToParameter(Value);
+
+                return new InjectionParameter(ValueType, null);
+            }
+        }
+
+        internal InjectionValueBuilder(TypeResolver resolver, Type acceptsType) {
+            m_resolver = resolver;
+            DefaultType = acceptsType;
+        }
+
+        public Type ResolveType(string typeSpec) {
+            if (string.IsNullOrEmpty(typeSpec)) {
+                if (DefaultType == null)
+                    throw new Exception("The type must be specified");
+                return DefaultType;
+            }
+            return m_resolver.Resolve(typeSpec);
+        }
+
+        public void Visit(ITextValue value) {
+            ValueType = ResolveType(value.TypeName);
+
+            Value = string.IsNullOrEmpty(value.Value) ?
+                Safe.CreateDefaultValue(ValueType) :
+                TypeDescriptor.GetConverter(ValueType).ConvertFromString(value.Value);
+        }
+
+        public void Visit(ISerializedValue value) {
+            ValueType = ResolveType(value.TypeName);
+
+            var serializer = new XmlSerializer(ValueType);
+
+            using (var reader = value.GetReader())
+                Value = new InjectionParameter(ValueType, serializer.Deserialize(reader));
+        }
+
+        public void Visit(IDependencyReference value) {
+            ValueType = ResolveType(value.TypeName);
+            Value = new ResolvedParameter(ValueType, value.DependencyName);
+        }
+
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/InjectionValueContext.cs	Thu Apr 26 19:35:01 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-using System;
-using Unity.Injection;
-
-namespace Implab.ServiceHost.Unity {
-
-    public class InjectionValueContext {
-
-        readonly TypeResolver m_resolver;
-
-        public Type AcceptsType { get; private set; }
-
-        public object Value { get; set; }
-
-        internal InjectionValueContext(TypeResolver resolver, Type acceptsType) {
-            m_resolver = resolver;
-            AcceptsType = acceptsType;
-        }
-
-        public Type ResolveType(string typeSpec) {
-            if (string.IsNullOrEmpty(typeSpec)) {
-                if (AcceptsType == null)
-                    throw new Exception("The type must be specified");
-                return AcceptsType;
-            }
-            return m_resolver.Resolve(typeSpec);
-        }
-
-        public void Visit(ITextValue value) {
-
-        }
-
-        public void Visit(ISerializedValue value) {
-
-        }
-
-        public void Visit(IDependencyReference value) {
-            Value = new ResolvedParameter()
-        }
-
-    }
-}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/InstanceRegistrationContext.cs	Thu Apr 26 19:35:01 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-using System;
-
-namespace Implab.ServiceHost.Unity {
-    public class InstanceRegistrationContext : RegistrationContext {
-
-        readonly TypeResolver m_typeResolver;
-        public override TypeResolver Resolver { get { return m_typeResolver; } }
-
-        public InstanceRegistrationContext(TypeResolver resolver, Type registrationType) : base(registrationType) {
-            Safe.ArgumentNotNull(resolver, nameof(resolver));
-            m_typeResolver = resolver;
-        }
-
-        
-    }
-}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/LifetimeElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/LifetimeElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -4,7 +4,7 @@
 {
     public abstract class LifetimeElement
     {
-        public abstract LifetimeManager GetLifetimeManager(ContainerContext ctx);
+        public abstract LifetimeManager GetLifetimeManager(ContainerBuilder ctx);
         
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/MethodInjectionElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/MethodInjectionElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -12,7 +12,7 @@
         [XmlElement("default", typeof(DefaultParameterElement))]
         public InjectionParameterElement[] Parameters { get; set; }
 
-        internal override void Visit(RegistrationContext context) {
+        internal override void Visit(TypeRegistrationBuilder context) {
             context.Visit(this);
         }
     }
--- a/Implab.ServiceHost/Unity/NamespaceElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/NamespaceElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -8,7 +8,7 @@
         [XmlAttribute("name")]
         public string Name { get; set; }
 
-        public override void Visit(ContainerContext context) {
+        public override void Visit(ContainerBuilder context) {
             context.Visit(this);
         }
     }
--- a/Implab.ServiceHost/Unity/PropertyInjectionElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/PropertyInjectionElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -12,7 +12,7 @@
         [XmlElement("default", typeof(DefaultParameterElement))]
         public InjectionParameterElement Value { get; set; }
 
-        internal override void Visit(RegistrationContext context) {
+        internal override void Visit(TypeRegistrationBuilder context) {
             context.Visit(this);
         }
     }
--- a/Implab.ServiceHost/Unity/RegisterElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/RegisterElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -20,15 +20,9 @@
         [XmlElement("method", typeof(MethodInjectionElement))]
         public AbstractInjectionElement[] Injectors { get; set; }
 
-        public override void Visit(ContainerContext context) {
+        public override void Visit(ContainerBuilder context) {
             context.Visit(this);
         }
-
-        public virtual Type ResolveImplementationType(ContainerContext ctx) {
-            return string.IsNullOrEmpty(MapToType) ?
-                ResolveRegistrationType(ctx) :
-                ctx.Resolve(MapToType);
-        }
     }
     
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/RegistrationBuilder.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Xml.Serialization;
+using Implab.Xml;
+using Unity.Injection;
+using Unity.Registration;
+
+namespace Implab.ServiceHost.Unity {
+    public abstract class RegistrationBuilder {
+        public Type RegistrationType {
+            get;
+            private set;
+        }
+
+        protected RegistrationBuilder(Type registrationType) {
+            RegistrationType = registrationType;
+        }
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/RegistrationContext.cs	Thu Apr 26 19:35:01 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Linq;
-using System.Xml.Serialization;
-using Implab.Xml;
-using Unity.Injection;
-using Unity.Registration;
-
-namespace Implab.ServiceHost.Unity {
-    public abstract class RegistrationContext {
-        public Type RegistrationType {
-            get;
-            private set;
-        }
-
-        protected RegistrationContext(Type registrationType) {
-            RegistrationType = registrationType;
-        }
-    }
-}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/SerializedElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/SerializedElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -4,7 +4,7 @@
 
 namespace Implab.ServiceHost.Unity
 {
-    public class SerializedElement : AbstractRegistration {
+    public class SerializedElement : AbstractRegistration, ISerializedValue {
         [XmlAttribute("href")]
         public string Location { get; set; }
 
@@ -14,25 +14,24 @@
 
         [XmlAnyElement]
         public XmlElement[] Content { get; set; }
-        
-        public override void Visit(ContainerContext context) {
+
+        string ISerializedValue.TypeName {
+            get {
+                return string.IsNullOrEmpty(SerializedType) ? RegistrationType : SerializedType;
+            }
+        }
+
+        public override void Visit(ContainerBuilder context) {
             context.Visit(this);
         }
 
-        public virtual Type ResolveSerializedType(ContainerContext context) {
-            if(string.IsNullOrEmpty(SerializedType))
-                return ResolveRegistrationType(context);
-            return context.Resolve(SerializedType);
-        }
+        public XmlReader GetReader() {
+            if (!string.IsNullOrEmpty(Location))
+                return XmlReader.Create(Location);
+            if (Content != null && Content.Length > 0)
+                return Content[0].CreateNavigator().ReadSubtree();
 
-        public virtual object GetValue(ContainerContext context) {
-            var type = ResolveRegistrationType(context);
-            if (Content == null || Content.Length == 0)
-                return Safe.CreateDefaultValue(type);
-
-            var serializer = new XmlSerializer(type);
-            using(var reader = Content[0].CreateNavigator().ReadSubtree())
-                return serializer.Deserialize(reader);
+            throw new Exception("No content found, expected XML document");
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/SerializedParameterElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/SerializedParameterElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -1,18 +1,28 @@
+using System;
 using System.Xml;
 using System.Xml.Schema;
 using System.Xml.Serialization;
 
 namespace Implab.ServiceHost.Unity
 {
-    public class SerializedParameterElement : InjectionParameterElement {
+    public class SerializedParameterElement : InjectionParameterElement, ISerializedValue {
         [XmlAttribute("href")]
         public string Location { get; set; }
 
         [XmlAnyElement]
         public XmlElement[] Content { get; set; }
 
-        internal override object Resolve(RegistrationContext context) {
-            return context.Resolve(this);
+        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");
+        }
+
+        internal override void Visit(InjectionValueBuilder builder) {
+            builder.Visit(this);
         }
     }
 }
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/SimgletonLifetimeElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/SimgletonLifetimeElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -3,7 +3,7 @@
 namespace Implab.ServiceHost.Unity
 {
     public class SimgletonLifetimeElement : LifetimeElement {
-        public override LifetimeManager GetLifetimeManager(ContainerContext ctx) {
+        public override LifetimeManager GetLifetimeManager(ContainerBuilder ctx) {
             return new SingletonLifetimeManager();
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/TypeRegistrationBuilder.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Unity.Injection;
+using Unity.Registration;
+
+namespace Implab.ServiceHost.Unity {
+    public class TypeRegistrationBuilder : RegistrationBuilder {
+
+        readonly TypeResolver m_resolver;
+
+        readonly List<InjectionMember> m_injections = new List<InjectionMember>();
+
+        public InjectionMember[] Injections { get { return m_injections.ToArray(); } }
+
+        public Type ImplementationType {
+            get;
+            private set;
+        }
+
+        internal TypeRegistrationBuilder(TypeResolver resolver, Type registrationType, Type implementationType) : base(registrationType) {
+            ImplementationType = implementationType;
+
+            // when registering a generic mapping, register all generic parameter names as local types
+            if (ImplementationType.IsGenericTypeDefinition) {
+                m_resolver = new TypeResolver(resolver);
+
+                foreach (var p in ImplementationType.GetGenericArguments())
+                    m_resolver.AddMapping(p.Name, p);
+            } else {
+                m_resolver = resolver;
+            }
+        }
+
+        internal void Visit(ConstructorInjectionElement constructorInjection) {
+            
+
+            var parameters = constructorInjection.Parameters?
+                .Select(x => {
+                    var valueBuilder = new InjectionValueBuilder(m_resolver, null);
+                    x.Visit(valueBuilder);
+                    return valueBuilder.Injection;
+                })
+                .ToArray();
+
+            var injection = parameters != null ? new InjectionConstructor(parameters) : new InjectionConstructor();
+            m_injections.Add(injection);
+        }
+
+        internal void Visit(MethodInjectionElement methodInjection) {
+            var valueContext = new InjectionValueBuilder(m_resolver, null);
+
+            var parameters = methodInjection.Parameters?
+                .Select(x => {
+                    var valueBuilder = new InjectionValueBuilder(m_resolver, null);
+                    x.Visit(valueBuilder);
+                    return valueBuilder.Injection;
+                })
+                .ToArray();
+
+            var injection = parameters != null ? new InjectionMethod(methodInjection.Name, parameters) : new InjectionMethod(methodInjection.Name);
+            m_injections.Add(injection);
+        }
+
+        internal void Visit(PropertyInjectionElement propertyInjection) {
+            if (propertyInjection.Value == null)
+                throw new Exception($"A value value must be specified for the property '{propertyInjection.Name}'");
+
+            var propertyType = RegistrationType.GetProperty(propertyInjection.Name)?.PropertyType;
+            var valueContext = new InjectionValueBuilder(m_resolver, propertyType);
+
+            propertyInjection.Value.Visit(valueContext);
+            var injection = new InjectionProperty(propertyInjection.Name, valueContext.Injection);
+            m_injections.Add(injection);
+        }
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/TypeRegistrationContext.cs	Thu Apr 26 19:35:01 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Unity.Injection;
-using Unity.Registration;
-
-namespace Implab.ServiceHost.Unity {
-    public class TypeRegistrationContext : RegistrationContext {
-
-        readonly TypeResolver m_resolver;
-
-        readonly List<InjectionMember> m_injections = new List<InjectionMember>();
-
-        public InjectionMember[] Injections { get { return m_injections.ToArray(); } }
-
-        public Type ImplementationType {
-            get;
-            private set;
-        }
-
-        internal TypeRegistrationContext(TypeResolver resolver, Type registrationType, Type implementationType) : base(registrationType) {
-            ImplementationType = implementationType;
-
-            // when registering a generic mapping, register all generic parameter names as local types
-            if (ImplementationType.IsGenericTypeDefinition) {
-                m_resolver = new TypeResolver(resolver);
-
-                foreach (var p in ImplementationType.GetGenericArguments())
-                    m_resolver.AddMapping(p.Name, p);
-            } else {
-                m_resolver = resolver;
-            }
-        }
-
-        internal void Visit(ConstructorInjectionElement constructorInjection) {
-            var valueContext = new InjectionValueContext(m_resolver, null);
-
-            var parameters = constructorInjection.Parameters?.Select(x => x.Resolve(valueContext)).ToArray();
-
-            var injection = parameters != null ? new InjectionConstructor(parameters) : new InjectionConstructor();
-            m_injections.Add(injection);
-        }
-
-        internal void Visit(MethodInjectionElement methodInjection) {
-            var valueContext = new InjectionValueContext(m_resolver, null);
-
-            var parameters = methodInjection.Parameters?.Select(x => x.Resolve(valueContext)).ToArray();
-
-            var injection = parameters != null ? new InjectionMethod(methodInjection.Name, parameters) : new InjectionMethod(methodInjection.Name);
-            m_injections.Add(injection);
-        }
-
-        internal void Visit(PropertyInjectionElement propertyInjection) {
-            if (propertyInjection.Value == null)
-                throw new Exception($"A value value must be specified for the property '{propertyInjection.Name}'");
-
-            var propertyType = RegistrationType.GetProperty(propertyInjection.Name)?.PropertyType;
-            var valueContext = new InjectionValueContext(m_resolver, propertyType);
-
-            var parameter = propertyInjection.Value.Resolve(valueContext);
-            var injection = new InjectionProperty(propertyInjection.Name, parameter);
-            m_injections.Add(injection);
-        }
-    }
-}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ValueElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/ValueElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -3,11 +3,25 @@
 namespace Implab.ServiceHost.Unity {
     public class ValueElement : AbstractRegistration, ITextValue {
         
-        [XmlText]
         [XmlAttribute("value")]
         public string Value { get; set; }
 
-        public override void Visit(ContainerContext context) {
+        [XmlText]
+        public string Text { get; set; }
+
+        string ITextValue.Value {
+            get {
+                return string.IsNullOrEmpty(Value) ? Text : Value;
+            }
+        }
+
+        public string TypeName {
+            get {
+                return RegistrationType;
+            }
+        }
+
+        public override void Visit(ContainerBuilder context) {
             context.Visit(this);
         }
     }
--- a/Implab.ServiceHost/Unity/ValueParameterElement.cs	Thu Apr 26 19:35:01 2018 +0300
+++ b/Implab.ServiceHost/Unity/ValueParameterElement.cs	Fri Apr 27 04:47:52 2018 +0300
@@ -1,15 +1,13 @@
 using System.Xml.Serialization;
 
-namespace Implab.ServiceHost.Unity
-{
-    public class ValueParameterElement : InjectionParameterElement
-    {
+namespace Implab.ServiceHost.Unity {
+    public class ValueParameterElement : InjectionParameterElement, ITextValue {
         [XmlText]
         [XmlAttribute("value")]
         public string Value { get; set; }
 
-        internal override object Resolve(RegistrationContext context) {
-            return context.Resolve(this);
+        internal override void Visit(InjectionValueBuilder builder) {
+            builder.Visit(this);
         }
     }
 }
\ No newline at end of file