Mercurial > pub > ImplabNet
changeset 269:ff581cff7003 v3
Working on Unity container xml configuration
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 ",":