changeset 269:ff581cff7003 v3

Working on Unity container xml configuration
author cin
date Tue, 24 Apr 2018 01:46:02 +0300
parents 0be8a6ae8307
children ade80d94dfb5
files Implab.Playground/Program.cs Implab.Playground/data/sample.xml Implab.ServiceHost/Unity/AbstractInjectorElement.cs Implab.ServiceHost/Unity/AbstractRegistration.cs Implab.ServiceHost/Unity/AssemblyElement.cs Implab.ServiceHost/Unity/ConfigurationContext.cs Implab.ServiceHost/Unity/ConfigurationSchema.cs Implab.ServiceHost/Unity/ConstructorInjectorElement.cs Implab.ServiceHost/Unity/ContainerElement.cs Implab.ServiceHost/Unity/ContainerLifetimeElement.cs Implab.ServiceHost/Unity/ContextLifetimeElement.cs Implab.ServiceHost/Unity/HierarchicalLifetimeElement.cs Implab.ServiceHost/Unity/IConfigurationElement.cs Implab.ServiceHost/Unity/IncludeElement.cs Implab.ServiceHost/Unity/LifetimeElement.cs Implab.ServiceHost/Unity/MethodInjectorElement.cs Implab.ServiceHost/Unity/MethodInjectorParameter.cs Implab.ServiceHost/Unity/NamespaceElement.cs Implab.ServiceHost/Unity/PropertyInjectorElement.cs Implab.ServiceHost/Unity/RegisterElement.cs Implab.ServiceHost/Unity/ServiceElement.cs Implab.ServiceHost/Unity/SimgletonLifetimeElement.cs Implab.ServiceHost/Unity/TypeReferenceParser.cs
diffstat 23 files changed, 277 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/Implab.Playground/Program.cs	Sun Apr 22 15:29:10 2018 +0300
+++ b/Implab.Playground/Program.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -9,6 +9,11 @@
 namespace Implab.Playground {
 
     public class Foo {
+
+        public class Bar {
+
+        }
+
         public int IntValue { get; set; }
 
         public string StringValue { get; set; }
@@ -32,20 +37,10 @@
         static void Main(string[] args) {
             var container = new UnityContainer();
 
-            var listener = new SimpleTraceListener(Console.Out);
-            Trace<ConfigurationContext>.TraceSource.Switch.Level = SourceLevels.All;
-            Trace<ConfigurationContext>.TraceSource.Listeners.Add(listener);
-
-            var c = new Container<int>();
+            var conf = SerializationHelpers.DeserializeFromFile<ContainerElement>("data/sample.xml");
 
-            var cts = new ConfigurationContext();
-            cts.AddNamespace("System");
-            cts.AddNamespace("System.Collections.Generic");
-            cts.AddNamespace("Implab.Playground");
+            Console.WriteLine($"Registrations: {conf.Registrations.Count}");
 
-            Console.WriteLine(c.GetType().FullName);
-
-            cts.Resolve("Container{Int32}");
         }
 
 
--- a/Implab.Playground/data/sample.xml	Sun Apr 22 15:29:10 2018 +0300
+++ b/Implab.Playground/data/sample.xml	Tue Apr 24 01:46:02 2018 +0300
@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <container xmlns="http://implab.org/schemas/servicehost/unity.v1.xsd">
     <!-- foo1 -->
-    <register name="foo1" provides="IFoo" type="Foo">
+    <register name="foo1" type="Foo">
     </register>
 
     <!-- foo2 -->
-    <register name="foo2" provides="IFoo" type="Foo">
+    <register name="foo2" type="Foo">
     </register>
 </container>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/AbstractInjectorElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,7 @@
+namespace Implab.ServiceHost.Unity
+{
+    public abstract class AbstractInjectorElement
+    {
+        
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/AbstractRegistration.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,22 @@
+using System;
+using System.Xml.Serialization;
+using Unity.Lifetime;
+using Unity.Registration;
+
+namespace Implab.ServiceHost.Unity
+{
+    public abstract class AbstractRegistration : IConfigurationElement {
+
+        /// <summary>
+        /// An optional name for a registration in the container
+        /// </summary>
+        [XmlAttribute("name")]
+        public string Name {
+            get; set;
+        }
+
+        public void Visit(ConfigurationContext context) {
+            context.Visist(this);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/AssemblyElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,14 @@
+using System.Xml.Serialization;
+
+namespace Implab.ServiceHost.Unity
+{
+    [XmlRoot("assembly", Namespace = Schema.ContainerConfigurationNamespace)]
+    public class AssemblyElement : IConfigurationElement {
+        [XmlAttribute("name")]
+        public string AssemblyName { get; set; }
+        
+        public void Visit(ConfigurationContext context) {
+            throw new System.NotImplementedException();
+        }
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ConfigurationContext.cs	Sun Apr 22 15:29:10 2018 +0300
+++ b/Implab.ServiceHost/Unity/ConfigurationContext.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -5,7 +5,9 @@
 
 namespace Implab.ServiceHost.Unity {
     using System.Linq;
+    using System.Reflection;
     using System.Text;
+    using global::Unity;
     using static Trace<ConfigurationContext>;
 
     public class ConfigurationContext {
@@ -14,7 +16,10 @@
 
         LinkedListNode<string> m_insertAt;
 
-        public ConfigurationContext() {
+        readonly UnityContainer m_container;
+
+        public ConfigurationContext(UnityContainer container) {
+            m_container = container ?? new UnityContainer();
             m_insertAt = new LinkedListNode<string>(string.Empty);
             m_namespases.AddFirst(m_insertAt);
         }
@@ -36,9 +41,9 @@
             foreach (var ns in m_namespases) {
                 var typeName = FormatName(new [] { ns, reference.Namespace, reference.TypeName}, argc, args, reference.IsArray);
 
-                var resolved = Type.GetType(typeName, false);
+                var resolved = ProbeType(typeName);
                 if (resolved != null) {
-                    Log("Probe succeed {0} in '{1}': {2} -> {3}", reference, ns, typeName, resolved.FullName);
+                    Log("Probe succeed {0} in '{1}': {2} -> {3}", reference, ns, typeName, resolved.AssemblyQualifiedName);
                     return resolved;
                 } else {
                     Log("Probe failed {0} in '{1}': {2}", reference, ns, typeName);
@@ -48,6 +53,17 @@
             throw new Exception($"Failed to resolve: {reference}");
         }
 
+        Type ProbeType(string typeName) {
+            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
+
+            foreach(var assembly in assemblies) {
+                var type = assembly.GetType(typeName);
+                if (type != null)
+                    return type;
+            }
+            return null;
+        }
+
         string FormatName(string[] parts, int argc, Type[] args, bool isArray) {
             var builder = new StringBuilder();
             
@@ -59,7 +75,7 @@
 
             if (args!= null && args.Length > 0) {
                 builder.Append('[');
-                builder.Append(string.Join(",", args.Select(x => x.FullName)));
+                builder.Append(string.Join(",", args.Select(x => $"[{x.AssemblyQualifiedName}]")));
                 builder.Append(']');
             }
 
@@ -73,7 +89,11 @@
             return Resolve(TypeReference.Parse(typeReference));
         }
 
-        public void Register(ServiceElement descriptor) {
+        public void Visist(AbstractRegistration descriptor) {
+            
+        }
+
+        public void Include(string file) {
 
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/ConfigurationSchema.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Xml;
+using System.Xml.Serialization;
+using Implab.Components;
+
+namespace Implab.ServiceHost.Unity {
+    public class ConfigurationSchema {
+
+        public static ConfigurationSchema Default { get; private set; } = CreateDefault();
+
+        readonly Dictionary<Tuple<string,string>, LazyAndWeak<XmlSerializer>> m_mappings = new Dictionary<Tuple<string, string>, LazyAndWeak<XmlSerializer>>();
+
+        public void DefineMapping(string name, string ns, Type type) {
+            Safe.ArgumentNotEmpty(name, nameof(name));
+            Safe.ArgumentNotNull(type, nameof(type));
+            ns = ns ?? string.Empty;
+            m_mappings[Tuple.Create(name, ns)] = new LazyAndWeak<XmlSerializer>(() => new XmlSerializer(type), true);
+        }
+
+        public void DefineMapping<T>() {
+            var xmlRoot = typeof(T).GetCustomAttribute<XmlRootAttribute>();
+            var ns = xmlRoot?.Namespace;
+            var root = xmlRoot?.ElementName ?? typeof(T).Name;
+            DefineMapping(root, ns, typeof(T));
+        }
+
+        public T Deserialize<T>(XmlReader reader) {
+            reader.MoveToContent();
+            var name = reader.Name;
+            var ns = reader.NamespaceURI;
+
+            return (T)m_mappings[Tuple.Create(name, ns)].Value.Deserialize(reader);
+        }
+
+        static ConfigurationSchema CreateDefault() {
+            var schema  = new ConfigurationSchema();
+
+            schema.DefineMapping<RegisterElement>();
+
+            return schema;
+        }
+
+
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/ConstructorInjectorElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,5 @@
+namespace Implab.ServiceHost.Unity {
+    public class ConstructorInjectorElement : AbstractInjectorElement {
+
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ContainerElement.cs	Sun Apr 22 15:29:10 2018 +0300
+++ b/Implab.ServiceHost/Unity/ContainerElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -8,7 +8,7 @@
     [XmlRoot("container", Namespace = Schema.ContainerConfigurationNamespace)]
     public class ContainerElement : IXmlSerializable {
 
-        public List<ServiceElement> Registrations {get; set; } = new List<ServiceElement>();
+        public List<IConfigurationElement> Registrations {get; set; } = new List<IConfigurationElement>();
 
         public XmlSchema GetSchema() {
             return null;
@@ -16,7 +16,7 @@
 
         public void ReadXml(XmlReader reader) {
             while(reader.Read() && reader.NodeType != XmlNodeType.EndElement) {
-                var registration = SerializationHelpers.Deserialize<ServiceElement>(reader);
+                var registration = ConfigurationSchema.Default.Deserialize<IConfigurationElement>(reader);
                 Registrations.Add(registration);
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/ContainerLifetimeElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,10 @@
+using Unity.Lifetime;
+
+namespace Implab.ServiceHost.Unity
+{
+    public class ContainerLifetimeElement : LifetimeElement {
+        public override LifetimeManager GetLifetimeManager(ConfigurationContext ctx) {
+            return new ContainerControlledLifetimeManager();
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/ContextLifetimeElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,10 @@
+using Unity.Lifetime;
+
+namespace Implab.ServiceHost.Unity
+{
+    public class ContextLifetimeElement : LifetimeElement {
+        public override LifetimeManager GetLifetimeManager(ConfigurationContext ctx) {
+            return new PerResolveLifetimeManager();
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/HierarchicalLifetimeElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,10 @@
+using Unity.Lifetime;
+
+namespace Implab.ServiceHost.Unity
+{
+    public class HierarchicalLifetimeElement : LifetimeElement {
+        public override LifetimeManager GetLifetimeManager(ConfigurationContext ctx) {
+            return new HierarchicalLifetimeManager();
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/IConfigurationElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,5 @@
+namespace Implab.ServiceHost.Unity {
+    public interface IConfigurationElement {
+        void Visit(ConfigurationContext context);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/IncludeElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,13 @@
+using System.Xml.Serialization;
+
+namespace Implab.ServiceHost.Unity {
+    [XmlRoot("include", Namespace = Schema.ContainerConfigurationNamespace)]
+    public class IncludeElement : IConfigurationElement {
+        [XmlAttribute("href")]
+        public string Href { get; set; }
+
+        public void Visit(ConfigurationContext context) {
+            context.Include(Href);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/LifetimeElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,10 @@
+using Unity.Lifetime;
+
+namespace Implab.ServiceHost.Unity
+{
+    public abstract class LifetimeElement
+    {
+        public abstract LifetimeManager GetLifetimeManager(ConfigurationContext ctx);
+        
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/MethodInjectorElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,13 @@
+using System.Xml.Serialization;
+
+namespace Implab.ServiceHost.Unity {
+    public class MethodInjectorElement : AbstractInjectorElement {
+
+        [XmlAttribute("name")]
+        public string Name { get; set; }
+
+        [XmlElement("params")]
+        public MethodInjectorParameter[] Parameters { get; set; }
+
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/MethodInjectorParameter.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,7 @@
+namespace Implab.ServiceHost.Unity
+{
+    public class MethodInjectorParameter
+    {
+        
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/NamespaceElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,15 @@
+using System.Xml.Serialization;
+
+namespace Implab.ServiceHost.Unity
+{
+    [XmlRoot("namespace", Namespace = Schema.ContainerConfigurationNamespace)]
+    public class NamespaceElement : IConfigurationElement {
+
+        [XmlAttribute("name")]
+        public string Name { get; set; }
+
+        public void Visit(ConfigurationContext context) {
+            throw new System.NotImplementedException();
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/PropertyInjectorElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,6 @@
+namespace Implab.ServiceHost.Unity {
+    public class PropertyInjectorElement : AbstractInjectorElement {
+
+
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/RegisterElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,36 @@
+using System;
+using System.Xml.Serialization;
+using Unity.Lifetime;
+using Unity.Registration;
+
+namespace Implab.ServiceHost.Unity {
+
+    [XmlRoot("register", Namespace = Schema.ContainerConfigurationNamespace)]
+    public class RegisterElement : AbstractRegistration  {
+        
+        /// <summary>
+        /// An optional type specification for the service registration, 
+        /// must be assignable from the type specified by <see cref="ImplementedType"/>
+        /// </summary>
+        [XmlAttribute("provides")]
+        public string ProvidesType { get; set; }
+
+        /// <summary>
+        /// The type which is registered as a service in the container.
+        /// </summary>
+        [XmlAttribute("type")]
+        public string ImplementedType { get; set; }
+
+        [XmlElement("signleton", typeof(SimgletonLifetimeElement))]
+        [XmlElement("context", typeof(ContextLifetimeElement))]
+        [XmlElement("container", typeof(ContainerLifetimeElement))]
+        [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))]
+        public LifetimeElement Lifetime {get; set;}
+
+        [XmlElement("constructor", typeof(ConstructorInjectorElement))]
+        [XmlElement("property", typeof(PropertyInjectorElement))]
+        [XmlElement("method", typeof(MethodInjectorElement))]
+        public AbstractInjectorElement[] Injectors { get; set; }
+    }
+    
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/ServiceElement.cs	Sun Apr 22 15:29:10 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-using System;
-using System.Xml.Serialization;
-
-namespace Implab.ServiceHost.Unity {
-
-    [XmlRoot("register", Namespace = Schema.ContainerConfigurationNamespace)]
-    public class ServiceElement {
-        /// <summary>
-        /// An optional name for a registration in the container
-        /// </summary>
-        [XmlAttribute("name")]
-        public string Name { get; set; }
-
-        /// <summary>
-        /// An optional type specification for the service registration, 
-        /// must be assignable from the type specified by <see cref="ImplementedType"/>
-        /// </summary>
-        [XmlAttribute("provides")]
-        public string ProvidesType { get; set; }
-
-        /// <summary>
-        /// The type which is registered as a service in the container.
-        /// </summary>
-        [XmlAttribute("type")]
-        public string ImplementedType { get; set; }
-    }
-    
-}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab.ServiceHost/Unity/SimgletonLifetimeElement.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -0,0 +1,10 @@
+using Unity.Lifetime;
+
+namespace Implab.ServiceHost.Unity
+{
+    public class SimgletonLifetimeElement : LifetimeElement {
+        public override LifetimeManager GetLifetimeManager(ConfigurationContext ctx) {
+            return new SingletonLifetimeManager();
+        }
+    }
+}
\ No newline at end of file
--- a/Implab.ServiceHost/Unity/TypeReferenceParser.cs	Sun Apr 22 15:29:10 2018 +0300
+++ b/Implab.ServiceHost/Unity/TypeReferenceParser.cs	Tue Apr 24 01:46:02 2018 +0300
@@ -20,7 +20,7 @@
             Eof
         }
 
-        readonly Regex _tokens = new Regex(@"(\w+)|\s*([\.{},\+])\s*");
+        readonly Regex _tokens = new Regex(@"([\w\+]+)|\s*([\.{},])\s*");
 
         TokenType m_token;
 
@@ -68,7 +68,6 @@
                             m_token = TokenType.CloseList;
                             break;
                         case ".":
-                        case "+":
                             m_token = TokenType.Dot;
                             break;
                         case ",":