##// END OF EJS Templates
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)...
cin -
r278:6691aff01de1 v3
parent child
Show More
@@ -0,0 +1,57
1 using System;
2 using System.Text;
3
4 namespace Implab.ServiceHost.Unity {
5 public class ArrayTypeReference : TypeReference {
6 public int Rank { get; private set; }
7
8 public TypeReference ItemsType { get; private set; }
9
10 public override string Name {
11 get {
12 return ItemsType.Name;
13 }
14 }
15
16 public override string ClrName {
17 get {
18 return new StringBuilder()
19 .Append(ItemsType.ClrName)
20 .Append("[")
21 .Append(',', Rank - 1)
22 .Append("]")
23 .ToString();
24 }
25 }
26
27 public override string Namespace {
28 get {
29 return ItemsType.Namespace;
30 }
31 }
32
33 public override int GenericParametersCount {
34 get {
35 return 0;
36 }
37 }
38
39 internal ArrayTypeReference(TypeReference itemsType, int rank) {
40 ItemsType = itemsType;
41 Rank = rank;
42 }
43
44 internal override void Visit(TypeResolutionContext visitor) {
45 visitor.Visit(this);
46 }
47
48 override public string ToString() {
49 return new StringBuilder()
50 .Append(ItemsType.ToString())
51 .Append('[')
52 .Append(',', Rank - 1)
53 .Append(']')
54 .ToString();
55 }
56 }
57 } No newline at end of file
@@ -0,0 +1,29
1 using System;
2
3 namespace Implab.ServiceHost.Unity {
4 public class FactoryActivator : FactoryAbstractRegistratrion {
5
6 public Type FactoryType { get; set; }
7
8 public string FactoryName { get; set; }
9
10 public new Type RegistrationType { get; set; }
11
12 public override void Visit(FactoryRegistrationBuilder builder) {
13 base.Visit(builder);
14
15 builder.GetType()
16 .GetMethod(
17 nameof(FactoryRegistrationBuilder.SetFactoryDependency)
18 , new[] { typeof(string) }
19 )
20 .MakeGenericMethod(FactoryType, RegistrationType)
21 .Invoke(builder, new[] { FactoryName });
22 }
23
24 public override Type GetRegistrationType(Func<string, Type> resolver) {
25 return RegistrationType;
26 }
27
28 }
29 } No newline at end of file
@@ -0,0 +1,72
1 using System;
2 using System.Xml.Serialization;
3 using Implab.Components;
4
5 namespace Implab.ServiceHost.Unity {
6 /// <summary>
7 /// Расширяет стандартную регистрацию типа до фабрики, вместе с регистрацией
8 /// самой фабрики создаются регистрации сервисов, которые она предоставляет.
9 /// </summary>
10 public class FactoryElement : RegisterElement {
11
12 /// <summary>
13 /// Записи о сервисах, которые создаются данной фабрикой.
14 /// </summary>
15 /// <remarks>
16 /// Сервисы, которые указаны в регистарциях они должны соответсвовать тому,
17 /// что фабрика возвращает, но это остается на откуп контейнера
18 /// </remarks>
19 [XmlElement("provides")]
20 public ProvidesElement[] Provides { get; set; }
21
22 /// <summary>
23 /// Переопределяет стандарное поведение регистрации типа в контейнере,
24 /// дополняя его регистрацией фабричных методов для получения типов.
25 /// </summary>
26 /// <param name="builder">Объект для конфигурирования контейнера.</param>
27 public override void Visit(ContainerBuilder builder) {
28 var factoryType = GetRegistrationType(builder.ResolveType);
29
30 base.Visit(builder);
31
32 if (Provides != null && Provides.Length > 0) {
33 // если регистрации явно заданы, используеися информация из них
34 foreach(var item in Provides) {
35 var activator = new FactoryActivator {
36 Name = item.RegistrationName,
37 RegistrationType = builder.ResolveType(item.RegistrationType),
38 FactoryName = Name,
39 FactoryType = factoryType
40 };
41 activator.Visit(builder);
42 }
43 } else {
44 // если регистрация явно не задана, в качестве сервиса для регистрации
45 // используется тип создаваемый фабрикой, который будет добавлен в контейнер
46 // с темже именем, что и сама фабрика (разные типы могут иметь одно имя для регистрации)
47 var providedType = (
48 factoryType.IsGenericType && factoryType.GetGenericTypeDefinition() == typeof(IFactory<>) ?
49 factoryType :
50 factoryType.GetInterface(typeof(IFactory<>).FullName)
51 )?
52 .GetGenericArguments()[0];
53
54 // не удалось определеить тип
55 if (providedType == null)
56 throw new ArgumentException("Failed to determine a type provided by the factory");
57
58 if (providedType.IsGenericParameter)
59 throw new ArgumentException("Can't register a generic type paramter as a service");
60
61 var activator = new FactoryActivator {
62 Name = Name,
63 RegistrationType = providedType,
64 FactoryName = Name,
65 FactoryType = factoryType
66 };
67
68 activator.Visit(builder);
69 }
70 }
71 }
72 } No newline at end of file
@@ -0,0 +1,5
1 namespace Implab.ServiceHost.Unity {
2 public interface IFactoryMemberInjection {
3 void Visit(FactoryRegistrationBuilder builder);
4 }
5 } No newline at end of file
@@ -0,0 +1,7
1 using System.Collections.Generic;
2
3 namespace Implab.ServiceHost.Unity {
4 public interface IFactoryRegistration : IRegistration {
5 IEnumerable<IFactoryMemberInjection> MemberInjections { get; }
6 }
7 } No newline at end of file
@@ -0,0 +1,5
1 namespace Implab.ServiceHost.Unity {
2 public interface IInjectionParameter {
3 void Visit(InjectionParameterBuilder builder);
4 }
5 } No newline at end of file
@@ -0,0 +1,8
1 using System.Collections.Generic;
2
3 namespace Implab.ServiceHost.Unity {
4 public interface IInstanceRegistration : IRegistration {
5
6 IEnumerable<IInjectionParameter> MemberInjections { get; }
7 }
8 } No newline at end of file
@@ -0,0 +1,12
1 using System;
2 using Unity.Lifetime;
3
4 namespace Implab.ServiceHost.Unity {
5 public interface IRegistration {
6 string Name { get; }
7
8 Type GetRegistrationType(ContainerBuilder builder);
9
10 LifetimeManager GetLifetime(ContainerBuilder builder);
11 }
12 } No newline at end of file
@@ -0,0 +1,6
1 namespace Implab.ServiceHost.Unity
2 {
3 public interface ITypeMemberInjection {
4 void Visit(TypeRegistrationBuilder builder);
5 }
6 } No newline at end of file
@@ -0,0 +1,10
1 using System;
2 using System.Collections.Generic;
3
4 namespace Implab.ServiceHost.Unity {
5 public interface ITypeRegistration : IRegistration {
6 Type GetImplementationType(ContainerBuilder builder);
7
8 IEnumerable<ITypeMemberInjection> MemberInjections { get; }
9 }
10 } No newline at end of file
@@ -0,0 +1,48
1 using System;
2 using System.Text;
3
4 namespace Implab.ServiceHost.Unity {
5 public class NestedTypeReference : TypeReference {
6
7 readonly string m_name;
8
9 readonly int m_genericParametersCount;
10
11 public TypeReference DeclaringType { get; private set; }
12
13 public override string Name {
14 get {
15 return m_name;
16 }
17 }
18
19 public override string Namespace {
20 get {
21 return DeclaringType.Namespace;
22 }
23 }
24
25 public override int GenericParametersCount {
26 get {
27 return m_genericParametersCount;
28 }
29 }
30
31 internal NestedTypeReference(TypeReference declaringType, string name, int parametersCount) {
32 DeclaringType = declaringType;
33 m_name = name;
34 m_genericParametersCount = parametersCount;
35 }
36
37 internal override void Visit(TypeResolutionContext visitor) {
38 visitor.Visit(this);
39 }
40
41 internal override void WriteTypeName(StringBuilder builder) {
42 builder
43 .Append(DeclaringType)
44 .Append('+')
45 .Append(Name);
46 }
47 }
48 } No newline at end of file
@@ -0,0 +1,11
1 using System.Xml.Serialization;
2
3 namespace Implab.ServiceHost.Unity {
4 public class ProvidesElement {
5 [XmlAttribute("type")]
6 public string RegistrationType { get; set; }
7
8 [XmlAttribute("name")]
9 public string RegistrationName { get; set; }
10 }
11 } No newline at end of file
@@ -0,0 +1,36
1 using System;
2
3 namespace Implab.ServiceHost.Unity
4 {
5 public class RootTypeReference : TypeReference {
6 readonly string m_name;
7
8 readonly string m_namespace;
9
10 readonly int m_genericParametersCount;
11
12 public override string Name {
13 get { return m_name; }
14 }
15
16 public override string Namespace {
17 get { return m_namespace; }
18 }
19
20 public override int GenericParametersCount {
21 get { return m_genericParametersCount; }
22 }
23
24 internal RootTypeReference(string ns, string name, int genericParameters) {
25 m_name = name;
26 m_genericParametersCount = genericParameters;
27 m_namespace = ns;
28 }
29
30 internal override void Visit(TypeResolutionContext visitor) {
31 visitor.Visit(this);
32 }
33
34
35 }
36 } No newline at end of file
@@ -0,0 +1,52
1 using System;
2 using System.Linq;
3 using System.Text;
4
5 namespace Implab.ServiceHost.Unity {
6 public class SpecializedTypeReference : TypeReference {
7 public override string Name {
8 get {
9 return GenericType.Name;
10 }
11 }
12
13 public override string Namespace {
14 get {
15 return GenericType.Namespace;
16 }
17 }
18
19 public override int GenericParametersCount {
20 get {
21 return GenericParameters.Length;
22 }
23 }
24
25 public TypeReference GenericType { get; private set; }
26
27 public TypeReference[] GenericParameters { get; private set; }
28
29 internal SpecializedTypeReference(TypeReference genericType, TypeReference[] genericParameters) {
30 GenericType = genericType;
31 GenericParameters = genericParameters;
32 }
33
34 internal override void Visit(TypeResolutionContext visitor) {
35 visitor.Visit(this);
36 }
37
38 internal override void WriteTypeName(StringBuilder builder) {
39 GenericType.WriteTypeName(builder);
40 }
41
42 internal override void WriteTypeParams(StringBuilder builder) {
43 builder.Append('{');
44 for (var i = 0; i < GenericParameters.Length; i++) {
45 if (i > 0)
46 builder.Append(',');
47 builder.Append(GenericParameters[i]);
48 }
49 builder.Append('}');
50 }
51 }
52 } No newline at end of file
@@ -0,0 +1,75
1 using System;
2 using System.Collections.Generic;
3 using Implab.Diagnostics;
4
5 namespace Implab.ServiceHost.Unity {
6 using static Trace<TypeResolver>;
7
8 /// <summary>
9 /// Позволяет обойти вложенные типы и собрать цеочку из типов и параметров генериков, которые они предлагают
10 /// </summary>
11 internal class TypeResolutionContext {
12 readonly TypeResolver m_resolver;
13
14
15 readonly List<Type> m_genericParameters = new List<Type>();
16
17 public IEnumerable<Type> GenericParameters { get { return m_genericParameters; } }
18
19 public Type ResolvedType { get; private set; }
20
21
22 public int ArrayRank { get; private set; }
23
24
25 public bool ThrowOnFail { get; private set; }
26
27 public TypeResolutionContext(TypeResolver resolver, bool throwOnFail) {
28 m_resolver = resolver;
29 ThrowOnFail = throwOnFail;
30 }
31
32 public Type MakeType() {
33 return m_genericParameters.Count > 0 ?
34 ResolvedType?.MakeGenericType(m_genericParameters.ToArray()) :
35 ResolvedType;
36 }
37
38 public void Visit(SpecializedTypeReference typeReference) {
39 typeReference.GenericType.Visit(this);
40
41 if (ResolvedType != null) {
42 foreach (var genericParamRef in typeReference.GenericParameters) {
43 var context = new TypeResolutionContext(m_resolver, ThrowOnFail);
44 genericParamRef.Visit(context);
45 m_genericParameters.Add(context.MakeType());
46 }
47 }
48 }
49
50 public void Visit(NestedTypeReference typeReference) {
51 typeReference.DeclaringType.Visit(this);
52 if (ResolvedType != null)
53 ResolvedType = ResolvedType?.GetNestedType(typeReference.ClrName) ?? Failed(typeReference);
54 }
55
56 public void Visit(RootTypeReference typeReference) {
57 ResolvedType = m_resolver.Resolve(typeReference.Namespace, typeReference.ClrName) ?? Failed(typeReference);
58 }
59
60 public void Visit(ArrayTypeReference typeReference) {
61 var context = new TypeResolutionContext(m_resolver, ThrowOnFail);
62 typeReference.ItemsType.Visit(context);
63 ResolvedType = typeReference.Rank == 1 ?
64 context.MakeType()?.MakeArrayType() :
65 context.MakeType()?.MakeArrayType(typeReference.Rank);
66 }
67
68 Type Failed(TypeReference reference) {
69 Log($"Falied to resolve {reference}");
70 if (ThrowOnFail)
71 throw new Exception($"Failed to resolve {reference}");
72 return null;
73 }
74 }
75 } No newline at end of file
@@ -0,0 +1,14
1 using System.Xml.Serialization;
2 using Implab.Components;
3
4 namespace Implab.Xml {
5 /// <summary>
6 /// This class used to get default serializer for the specified type <typeparamref name="T"/>.
7 /// </summary>
8 /// <typeparam name="T">The type used to create <see cref="XmlSerializer"/></typeparam>
9 public static class XmlDefaultSerializer<T> {
10 static readonly LazyAndWeak<XmlSerializer> m_instance = new LazyAndWeak<XmlSerializer>(() => new XmlSerializer(typeof(T)));
11
12 public static XmlSerializer Instance { get { return m_instance.Value; } }
13 }
14 } No newline at end of file
@@ -0,0 +1,89
1 using System.IO;
2 using System.Text;
3 using System.Xml;
4 using System.Xml.Linq;
5 using System.Xml.Serialization;
6
7 namespace Implab.Xml {
8 public static class XmlSerializerExtensions {
9
10 public static void Serialize(this XmlSerializer that, object obj, XmlElement element) {
11 Safe.ArgumentNotNull(that, nameof(that));
12 using (var writer = element.CreateNavigator().AppendChild())
13 that.Serialize(writer, obj);
14 }
15
16 public static void Serialize(this XmlSerializer that, object obj, XElement element) {
17 Safe.ArgumentNotNull(that, nameof(that));
18 using (var writer = element.CreateWriter())
19 that.Serialize(writer, obj);
20 }
21
22 public static XDocument SerializeAsXDocumnet(this XmlSerializer that, object obj) {
23 Safe.ArgumentNotNull(that, nameof(that));
24 var doc = new XDocument();
25 using (var writer = doc.CreateWriter()) {
26 that.Serialize(writer, obj);
27 }
28 return doc;
29 }
30
31 public static XmlDocument SerializeAsXmlDocument(this XmlSerializer that, object obj) {
32 Safe.ArgumentNotNull(that, nameof(that));
33 var doc = new XmlDocument();
34 using (var writer = doc.CreateNavigator().AppendChild()) {
35 that.Serialize(writer, obj);
36 }
37 return doc;
38 }
39 public static string SerializeAsString(this XmlSerializer that, object obj) {
40 Safe.ArgumentNotNull(that, nameof(that));
41 using (var writer = new StringWriter()) {
42 that.Serialize(writer, obj);
43 return writer.ToString();
44 }
45 }
46
47 public static void SerializeToFile(this XmlSerializer that, object obj, string file, Encoding encoding) {
48 Safe.ArgumentNotNull(that, nameof(that));
49 using (var writer = new StreamWriter(File.Create(file),encoding))
50 that.Serialize(writer, obj);
51 }
52
53 public static void SerializeToFile(this XmlSerializer that, object obj, string file) {
54 SerializeToFile(that, obj, file, Encoding.UTF8);
55 }
56
57 public static object Deserialize(this XmlSerializer that, XmlElement element) {
58 Safe.ArgumentNotNull(that, nameof(that));
59 Safe.ArgumentNotNull(element, nameof(element));
60
61 using (var reader = element.CreateNavigator().ReadSubtree())
62 return that.Deserialize(reader);
63 }
64
65 public static object Deserialize(this XmlSerializer that, XElement element) {
66 Safe.ArgumentNotNull(that, nameof(that));
67 Safe.ArgumentNotNull(element, nameof(element));
68
69 using (var reader = element.CreateReader())
70 return that.Deserialize(reader);
71 }
72
73 public static object DeserializeFromString(this XmlSerializer that, string text) {
74 Safe.ArgumentNotNull(that, nameof(that));
75
76 using(var reader = new StringReader(text))
77 return that.Deserialize(reader);
78 }
79
80 public static object DeserializeFromFile(this XmlSerializer that, string file) {
81 Safe.ArgumentNotNull(that, nameof(that));
82
83 using(var reader = File.OpenRead(file))
84 return that.Deserialize(reader);
85 }
86
87
88 }
89 } No newline at end of file
@@ -1,114 +1,136
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Diagnostics;
3 using System.Diagnostics;
4 using System.Linq;
4 using System.Linq;
5 using Implab.Components;
5 using Implab.Diagnostics;
6 using Implab.Diagnostics;
6 using Implab.ServiceHost.Unity;
7 using Implab.ServiceHost.Unity;
7 using Implab.Xml;
8 using Implab.Xml;
8 using Unity;
9 using Unity;
9 using Unity.Injection;
10 using Unity.Injection;
10 using Unity.Registration;
11 using Unity.Registration;
11
12
12 namespace Implab.Playground {
13 namespace Implab.Playground {
13
14
14 public class Foo {
15 public class Foo {
15
16
16 public class Bar {
17 public class Bar {
17
18
18 }
19 }
19
20
20 public string Name { get; set; }
21 public string Name { get; set; }
21
22
22 public int IntValue { get; set; }
23 public int IntValue { get; set; }
23
24
24 public string StringValue { get; set; }
25 public string StringValue { get; set; }
25
26
26 public void AddRange(Foo[] items) {
27 public void AddRange(Foo[] items) {
27 Console.WriteLine($"AddRange: Foo[]");
28 Console.WriteLine($"AddRange: Foo[]");
28 }
29 }
29
30
30 }
31 }
31
32
33 public class FooFactory : IFactory<Foo>, IFactory<Foo.Bar> {
34
35 public bool UseSsl { get; set; }
36
37 public string Connection { get; set; }
38
39 public Foo Create() {
40 return new Foo() {
41 Name = "AutoFac"
42 };
43 }
44
45 Foo.Bar IFactory<Foo.Bar>.Create() {
46 return new Foo.Bar();
47 }
48 }
49
32 public interface IContainer<T> {
50 public interface IContainer<T> {
33 T Instance { get; set; }
51 T Instance { get; set; }
34 }
52 }
35
53
36 public class Container<T> : IContainer<T> {
54 public class Container<T> : IContainer<T> {
55 public class Bar {
56
57 }
58
59 public class Bar<T2> {
60 public class Baz {
61
62 }
63
64 }
65
37 public Container() {
66 public Container() {
38
67
39 }
68 }
40
69
41 public Container(T instance) {
70 public Container(T instance) {
42 Instance = instance;
71 Instance = instance;
43 }
72 }
44
73
45 public T Instance { get; set; }
74 public T Instance { get; set; }
46
75
47 public void SetInstance(T value) {
76 public void SetInstance(T value) {
48 Instance = value;
77 Instance = value;
49 }
78 }
50
79
51 public void AddRange(List<T> items) {
80 public void AddRange(List<T> items) {
52 Console.WriteLine($"AddRange: {typeof(List<T>)}");
81 Console.WriteLine($"AddRange: {typeof(List<T>)}");
53 }
82 }
54
83
55 public void AddRange(T[] items) {
84 public void AddRange(T[] items) {
56 Console.WriteLine($"AddRange: T[] ofType {typeof(T[])}");
85 Console.WriteLine($"AddRange: T[] ofType {typeof(T[])}");
57 }
86 }
58 }
87 }
59
88
60 public class Program {
89 public class Program {
61
90
62 static void Main(string[] args) {
91 static void Main(string[] args) {
63 var listener = new SimpleTraceListener(Console.Out);
92 var listener = new SimpleTraceListener(Console.Out);
64 var source = Trace<TypeResolver>.TraceSource;
93 var source = Trace<TypeResolver>.TraceSource;
65 source.Switch.Level = SourceLevels.All;
94 source.Switch.Level = SourceLevels.All;
66 source.Listeners.Add(listener);
95 source.Listeners.Add(listener);
67
96
68 var stopwatch = new Stopwatch();
97 var resolver = new TypeResolver();
69 stopwatch.Start();
98 resolver.AddNamespace("System");
70
99 resolver.AddNamespace("System.Collections.Generic");
71 var ctx = new ContainerBuilder();
100 resolver.AddNamespace("Implab.Playground");
72
101 resolver.AddMapping("string", typeof(string));
73 Console.WriteLine($"Created: {stopwatch.ElapsedMilliseconds}");
102 resolver.AddMapping("listOf`1", typeof(List<>));
74 stopwatch.Restart();
75
76 ctx.LoadConfig("data/sample.xml");
77
78 Console.WriteLine($"Loaded: {stopwatch.ElapsedMilliseconds}");
79
103
80 var container = ctx.Container;
104 var spec = TypeReference.Parse("Container{listOf{string}}+Bar{List{string}}");
81
105
82 stopwatch.Restart();
106 var t = resolver.Resolve(spec, true);
83 var instace1 = container.Resolve<IContainer<string>>();
84 Console.WriteLine($"Resolved1: {stopwatch.ElapsedMilliseconds}");
85
107
86 stopwatch.Restart();
108 Console.WriteLine("{0}", t);
87 var instace2 = container.Resolve<IContainer<Foo>>();
109 Console.WriteLine("Spec: {0}", spec);
88 Console.WriteLine($"Resolved2: {stopwatch.ElapsedMilliseconds}");
110 Console.WriteLine("IsGenericType: {0}", t.IsGenericType);
89
111 Console.WriteLine("IsGenericTypeDefinition: {0}", t.IsGenericTypeDefinition);
90 DisplayContainerRegistrations(container);
112 Console.WriteLine("ContainsGenericParameters: {0}", t.ContainsGenericParameters);
91 }
113 }
92
114
93 static void DisplayContainerRegistrations(IUnityContainer theContainer) {
115 static void DisplayContainerRegistrations(IUnityContainer theContainer) {
94 string regName, regType, mapTo, lifetime;
116 string regName, regType, mapTo, lifetime;
95 Console.WriteLine("Container has {0} Registrations:",
117 Console.WriteLine("Container has {0} Registrations:",
96 theContainer.Registrations.Count());
118 theContainer.Registrations.Count());
97 foreach (ContainerRegistration item in theContainer.Registrations) {
119 foreach (ContainerRegistration item in theContainer.Registrations) {
98 regType = item.RegisteredType.FullName;
120 regType = item.RegisteredType.FullName;
99 mapTo = item.MappedToType.FullName;
121 mapTo = item.MappedToType.FullName;
100 regName = item.Name ?? "[default]";
122 regName = item.Name ?? "[default]";
101 lifetime = item.LifetimeManager.LifetimeType.Name;
123 lifetime = item.LifetimeManager.LifetimeType.Name;
102 if (mapTo != regType) {
124 if (mapTo != regType) {
103 mapTo = " -> " + mapTo;
125 mapTo = " -> " + mapTo;
104 } else {
126 } else {
105 mapTo = string.Empty;
127 mapTo = string.Empty;
106 }
128 }
107 lifetime = lifetime.Substring(0, lifetime.Length - "LifetimeManager".Length);
129 lifetime = lifetime.Substring(0, lifetime.Length - "LifetimeManager".Length);
108 Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo, regName, lifetime);
130 Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo, regName, lifetime);
109 }
131 }
110 }
132 }
111
133
112
134
113 }
135 }
114 }
136 }
@@ -1,68 +1,74
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <container xmlns="http://implab.org/schemas/servicehost/unity.v1.xsd">
2 <container xmlns="http://implab.org/schemas/servicehost/unity.v1.xsd">
3 <namespace name="System"/>
3 <namespace name="System"/>
4 <namespace name="System.Collections.Generic"/>
4 <namespace name="System.Collections.Generic"/>
5 <namespace name="Implab.Components"/>
5 <namespace name="Implab.Playground"/>
6 <namespace name="Implab.Playground"/>
6
7
7 <!-- foo1 -->
8 <!-- foo1 -->
8 <register name="foo1" type="Foo">
9 <register name="foo1" type="Foo">
9 <property name="Name">
10 <property name="Name">
10 <value>FOO!</value>
11 <value>FOO!</value>
11 </property>
12 </property>
12 </register>
13 </register>
13
14
14 <!-- foo2 -->
15 <!-- foo2 -->
15 <register name="foo2" type="Foo">
16 <register name="foo2" type="Foo">
16 <property name="Name">
17 <property name="Name">
17 <value>GOOD</value>
18 <value>GOOD</value>
18 </property>
19 </property>
19 <property name="IntValue">
20 <property name="IntValue">
20 <value>2</value>
21 <value>2</value>
21 </property>
22 </property>
22 </register>
23 </register>
23
24
24 <register type="Foo">
25 <register type="Foo">
25 <method name="AddRange">
26 <method name="AddRange">
26 <array itemsType="Foo">
27 <array itemsType="Foo">
27 <dependency name="foo2"/>
28 <dependency name="foo2"/>
28 </array>
29 </array>
29 </method>
30 </method>
30 </register>
31 </register>
31
32
32 <register type="IContainer{}" mapTo="Container{}">
33 <register type="IContainer{}" mapTo="Container{}">
33 <constructor/>
34 <constructor/>
34 <method name="SetInstance">
35 <method name="SetInstance">
35 <dependency type="T"/>
36 <dependency type="T"/>
36 </method>
37 </method>
37 <method name="AddRange">
38 <method name="AddRange">
38 <array itemsType="T">
39 <array itemsType="T">
39 <dependency name="foo2"/>
40 <dependency name="foo2-bar"/>
40 </array>
41 </array>
41 </method>
42 </method>
42 </register>
43 </register>
43
44
44 <register type="List{}">
45 <register type="List{}">
45 <constructor />
46 <constructor />
46 </register>
47 </register>
47
48
48 <register type="IContainer{String}" mapTo="Container{String}">
49 <register type="IContainer{String}" mapTo="Container{String}">
49 <constructor/>
50 <constructor/>
50 <method name="SetInstance">
51 <method name="SetInstance">
51 <dependency type="String" name="name1"/>
52 <dependency type="String" name="name1"/>
52 </method>
53 </method>
53 </register>
54 </register>
54
55
55 <serialized type="Foo+Bar">
56 <serialized type="Foo+Bar">
56 <Bar xmlns="" id="1">
57 <Bar xmlns="" id="1">
57 <Name>Baaar</Name>
58 <Name>Baaar</Name>
58 </Bar>
59 </Bar>
59 </serialized>
60 </serialized>
60
61
61 <value name="connection1" type="String"><![CDATA[Connect me <here>!]]></value>
62 <value name="connection1" type="String"><![CDATA[Connect me <here>!]]></value>
62 <value name="name1" type="String" value="Hello!"/>
63 <value name="name1" type="String" value="Hello!"/>
63
64
64 <factory name="foo3" type="FooFactory">
65 <factory name="foo3" type="IFactory{Foo}" mapTo="FooFactory">
65 <parameter name="FooName"><![CDATA[Wired "" objecty <> name @#$%^&]]></parameter>
66 <property name="Connection">
67 <value><![CDATA[Wired "" objecty <> name @#$%^&]]></value>
68 </property>
69 <property name="UseSsl">
70 <value>false</value>
71 </property>
66 </factory>
72 </factory>
67
73
68 </container> No newline at end of file
74 </container>
@@ -1,20 +1,20
1 using System.Xml.Serialization;
1 using System.Xml.Serialization;
2
2
3 namespace Implab.ServiceHost.Unity
3 namespace Implab.ServiceHost.Unity
4 {
4 {
5 public class ArrayParameterElement : InjectionParameterElement {
5 public class ArrayParameterElement : InjectionParameterElement {
6
6
7 [XmlAttribute("itemsType")]
7 [XmlAttribute("itemsType")]
8 public string ItemsType { get; set; }
8 public string ItemsType { get; set; }
9
9
10 [XmlElement("dependency", typeof(DependencyParameterElement))]
10 [XmlElement("dependency", typeof(DependencyParameterElement))]
11 [XmlElement("value", typeof(ValueParameterElement))]
11 [XmlElement("value", typeof(ValueParameterElement))]
12 [XmlElement("serialized", typeof(SerializedParameterElement))]
12 [XmlElement("serialized", typeof(SerializedParameterElement))]
13 [XmlElement("default", typeof(DefaultParameterElement))]
13 [XmlElement("default", typeof(DefaultParameterElement))]
14 public InjectionParameterElement[] Items { get; set; }
14 public InjectionParameterElement[] Items { get; set; }
15
15
16 public override void Visit(InjectionValueBuilder builder) {
16 public override void Visit(InjectionParameterBuilder builder) {
17 builder.Visit(this);
17 builder.Visit(this);
18 }
18 }
19 }
19 }
20 } No newline at end of file
20 }
@@ -1,14 +1,14
1 using System.Xml.Serialization;
1 using System.Xml.Serialization;
2
2
3 namespace Implab.ServiceHost.Unity
3 namespace Implab.ServiceHost.Unity
4 {
4 {
5 [XmlRoot("assembly", Namespace = Schema.ContainerConfigurationNamespace)]
5 [XmlRoot("assembly", Namespace = Schema.ContainerConfigurationNamespace)]
6 public class AssemblyElement : AbstractContainerItem {
6 public class AssemblyElement : AbstractContainerItem {
7 [XmlAttribute("name")]
7 [XmlAttribute("name")]
8 public string AssemblyName { get; set; }
8 public string AssemblyName { get; set; }
9
9
10 public override void Visit(ContainerBuilder builder) {
10 public override void Visit(ContainerBuilder builder) {
11 builder.Visit(this);
11 builder.AddAssembly(AssemblyName);
12 }
12 }
13 }
13 }
14 } No newline at end of file
14 }
@@ -1,118 +1,177
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Reflection;
3 using System.Text.RegularExpressions;
3 using Unity;
4 using Implab.Diagnostics;
5
4
6 namespace Implab.ServiceHost.Unity {
5 namespace Implab.ServiceHost.Unity {
7 using System.Linq;
8 using System.Reflection;
9 using System.Text;
10 using global::Unity;
11 using global::Unity.Registration;
12 using Implab.Xml;
13 using static Trace<ContainerBuilder>;
14
15 public class ContainerBuilder {
6 public class ContainerBuilder {
16
7
17 readonly TypeResolver m_resolver;
8 readonly TypeResolver m_resolver;
18
9
19 readonly UnityContainer m_container;
10 readonly UnityContainer m_container;
20
11
21 readonly ContainerConfigurationSchema m_schema;
12 readonly ContainerConfigurationSchema m_schema;
22
13
23 public UnityContainer Container {
14 public UnityContainer Container {
24 get {
15 get {
25 return m_container;
16 return m_container;
26 }
17 }
27 }
18 }
28
19
29 public ContainerBuilder() : this(null, null) {
20 public ContainerBuilder() : this(null, null) {
30 }
21 }
31
22
32 public ContainerBuilder(UnityContainer container, ContainerConfigurationSchema schema) {
23 public ContainerBuilder(UnityContainer container, ContainerConfigurationSchema schema) {
33 m_container = container ?? new UnityContainer();
24 m_container = container ?? new UnityContainer();
34 m_resolver = new TypeResolver();
25 m_resolver = new TypeResolver();
35 m_schema = schema ?? ContainerConfigurationSchema.Default;
26 m_schema = schema ?? ContainerConfigurationSchema.Default;
36 }
27 }
37
28
38 public Type ResolveType(string typeReference) {
29 public Type ResolveType(string typeReference) {
39 return m_resolver.Resolve(typeReference);
30 return m_resolver.Resolve(typeReference, true);
40 }
31 }
41
32
42
33
43 internal void Visit(TypeAbstractRegistration typeRegistration) {
34 internal void Visit(TypeAbstractRegistration typeRegistration) {
44 var registrationType = typeRegistration.GetRegistrationType(ResolveType);
35 var registrationType = typeRegistration.GetRegistrationType(ResolveType);
45 var implementationType = typeRegistration.GetImplementationType(ResolveType) ?? registrationType;
36 var implementationType = typeRegistration.GetImplementationType(ResolveType) ?? registrationType;
46
37
47 var registrationContext = new TypeRegistrationBuilder(
38 var registrationContext = new TypeRegistrationBuilder(
48 m_resolver,
39 m_resolver,
49 registrationType,
40 registrationType,
50 implementationType
41 implementationType
51 );
42 );
52
43
53 typeRegistration.Visit(registrationContext);
44 typeRegistration.Visit(registrationContext);
54
45
55 m_container.RegisterType(
46 m_container.RegisterType(
56 registrationContext.RegistrationType,
47 registrationContext.RegistrationType,
57 registrationContext.ImplementationType,
48 registrationContext.ImplementationType,
58 typeRegistration.Name,
49 typeRegistration.Name,
59 registrationContext.Lifetime,
50 registrationContext.Lifetime,
60 registrationContext.Injections
51 registrationContext.Injections
61 );
52 );
62 }
53 }
63
54
64 internal void Visit(InstanceAbstractRegistration instanceRegistration) {
55 internal void Visit(InstanceAbstractRegistration instanceRegistration) {
65 var registrationType = instanceRegistration.GetRegistrationType(ResolveType);
56 var registrationType = instanceRegistration.GetRegistrationType(ResolveType);
66
57
67 var builder = new InstanceRegistrationBuilder(m_resolver, registrationType);
58 var builder = new InstanceRegistrationBuilder(m_resolver, registrationType);
68
59
69 instanceRegistration.Visit(builder);
60 instanceRegistration.Visit(builder);
70
61
71 m_container.RegisterInstance(
62 m_container.RegisterInstance(
72 builder.ValueBuilder.ValueType,
63 builder.ValueBuilder.ValueType,
73 instanceRegistration.Name,
64 instanceRegistration.Name,
74 builder.ValueBuilder.Value,
65 builder.ValueBuilder.Value,
75 builder.Lifetime
66 builder.Lifetime
76 );
67 );
77 }
68 }
78
69
79 internal void Visit(FactoryAbstractRegistratrion factoryRgistration) {
70 internal void Visit(FactoryAbstractRegistratrion factoryRgistration) {
80 var registrationType = factoryRgistration.GetRegistrationType(ResolveType);
71 var registrationType = factoryRgistration.GetRegistrationType(ResolveType);
81
72
82 var builder = new FactoryRegistrationBuilder(registrationType);
73 var builder = new FactoryRegistrationBuilder(registrationType);
83
74
84 factoryRgistration.Visit(builder);
75 factoryRgistration.Visit(builder);
85
76
86 m_container.RegisterType(
77 m_container.RegisterType(
87 builder.RegistrationType,
78 builder.RegistrationType,
88 factoryRgistration.Name,
79 factoryRgistration.Name,
89 builder.Lifetime,
80 builder.Lifetime,
90 builder.Factory
81 builder.Factory
91 );
82 );
92 }
83 }
93
84
94 internal void Visit(NamespaceElement namespaceElement) {
85 public void Visit(ITypeRegistration registration) {
95 m_resolver.AddNamespace(namespaceElement.Name);
86 Safe.ArgumentNotNull(registration, nameof(registration));
87
88 var registrationType = registration.GetRegistrationType(this);
89 var implementationType = registration.GetImplementationType(this) ?? registrationType;
90
91 if (registrationType == null)
92 throw new Exception($"A type must be specified for the registration {registration.Name}");
93
94 var builder = new TypeRegistrationBuilder(
95 m_resolver,
96 registrationType,
97 implementationType
98 );
99
100 builder.Lifetime = registration.GetLifetime(this);
101
102 if (registration.MemberInjections != null) {
103 foreach(var member in registration.MemberInjections)
104 member.Visit(builder);
105 }
106
107 m_container.RegisterType(
108 builder.RegistrationType,
109 builder.ImplementationType,
110 registration.Name,
111 builder.Lifetime,
112 builder.Injections
113 );
96 }
114 }
97
115
98 internal void Visit(AssemblyElement assemblyElement) {
116 public void Visit(IInstanceRegistration registration) {
99 Assembly.Load(assemblyElement.AssemblyName);
117 Safe.ArgumentNotNull(registration, nameof(registration));
118
119 var registrationType = registration.GetRegistrationType(this);
120
121 var builder = new InstanceRegistrationBuilder (
122 m_resolver,
123 registrationType
124 );
125
126 builder.Lifetime = registration.GetLifetime(this);
127
128 if (registration.MemberInjections != null) {
129 foreach(var member in registration.MemberInjections)
130 member.Visit(builder.ValueBuilder);
131 }
132
133 if (builder.RegistrationType == null && builder.ValueBuilder.ValueType == null)
134 throw new Exception($"A type must be specified for the registration {registration.Name}");
135
136 m_container.RegisterInstance(
137 builder.RegistrationType ?? builder.ValueBuilder.ValueType,
138 registration.Name,
139 builder.ValueBuilder.Injection,
140 builder.Lifetime
141 );
100 }
142 }
101
143
102 internal void Visit(IncludeElement includeElement) {
144 public void Visit(IFactoryRegistration registration) {
103 Include(includeElement.Href);
145 Safe.ArgumentNotNull(registration, nameof(registration));
146
147 var registrationType = registration.GetRegistrationType(this);
148
149 var builder = new FactoryRegistrationBuilder(registrationType);
150
151 if (registration.MemberInjections != null) {
152 foreach(var member in registration.MemberInjections)
153 member?.Visit(builder);
154 }
155
156 }
157
158 public void AddNamespace(string ns) {
159 m_resolver.AddNamespace(ns);
160 }
161
162 public void AddAssembly(string assembly) {
163
104 }
164 }
105
165
106 public void Include(string file) {
166 public void Include(string file) {
107 var includeContext = new ContainerBuilder(m_container, m_schema);
167 var includeContext = new ContainerBuilder(m_container, m_schema);
108 includeContext.LoadConfig(file);
168 includeContext.LoadConfig(file);
109 }
169 }
110
170
111 public void LoadConfig(string file) {
171 public void LoadConfig(string file) {
112 var config = m_schema.LoadFile(file);
172 var config = m_schema.LoadFile(file);
113
114 config.Visit(this);
173 config.Visit(this);
115 }
174 }
116
175
117 }
176 }
118 } No newline at end of file
177 }
@@ -1,69 +1,70
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.IO;
3 using System.IO;
4 using System.Reflection;
4 using System.Reflection;
5 using System.Xml;
5 using System.Xml;
6 using System.Xml.Serialization;
6 using System.Xml.Serialization;
7 using Implab.Components;
7 using Implab.Components;
8
8
9 namespace Implab.ServiceHost.Unity {
9 namespace Implab.ServiceHost.Unity {
10 public class ContainerConfigurationSchema {
10 public class ContainerConfigurationSchema {
11
11
12 public static ContainerConfigurationSchema Default { get; private set; } = CreateDefault();
12 public static ContainerConfigurationSchema Default { get; private set; } = CreateDefault();
13
13
14 readonly LazyAndWeak<XmlSerializer> m_seralizer;
14 readonly LazyAndWeak<XmlSerializer> m_seralizer;
15
15
16 readonly XmlAttributeOverrides m_overrides = new XmlAttributeOverrides();
16 readonly XmlAttributeOverrides m_overrides = new XmlAttributeOverrides();
17
17
18 readonly XmlAttributes m_containerItems = new XmlAttributes();
18 readonly XmlAttributes m_containerItems = new XmlAttributes();
19
19
20 public XmlSerializer Serializer {
20 public XmlSerializer Serializer {
21 get {
21 get {
22 return m_seralizer.Value;
22 return m_seralizer.Value;
23 }
23 }
24 }
24 }
25
25
26 public ContainerConfigurationSchema() {
26 public ContainerConfigurationSchema() {
27 m_overrides.Add(typeof(ContainerElement), nameof(ContainerElement.Items), m_containerItems);
27 m_overrides.Add(typeof(ContainerElement), nameof(ContainerElement.Items), m_containerItems);
28
28
29 m_seralizer = new LazyAndWeak<XmlSerializer>(() => new XmlSerializer(typeof(ContainerElement), m_overrides));
29 m_seralizer = new LazyAndWeak<XmlSerializer>(() => new XmlSerializer(typeof(ContainerElement), m_overrides));
30 }
30 }
31
31
32 public void RegisterContainerElement(Type type, string name) {
32 public void RegisterContainerElement(Type type, string name) {
33 Safe.ArgumentNotNull(type, nameof(type));
33 Safe.ArgumentNotNull(type, nameof(type));
34 Safe.ArgumentNotEmpty(name, nameof(name));
34 Safe.ArgumentNotEmpty(name, nameof(name));
35
35
36 if(!type.IsSubclassOf(typeof(AbstractContainerItem)))
36 if(!type.IsSubclassOf(typeof(AbstractContainerItem)))
37 throw new Exception($"RegisterContainerElement '{name}': {type} must be subclass of {typeof(AbstractContainerItem)}");
37 throw new Exception($"RegisterContainerElement '{name}': {type} must be subclass of {typeof(AbstractContainerItem)}");
38
38
39 m_containerItems.XmlElements.Add(
39 m_containerItems.XmlElements.Add(
40 new XmlElementAttribute(name, type)
40 new XmlElementAttribute(name, type)
41 );
41 );
42 }
42 }
43
43
44 public void RegisterContainerElement<T>(string name) where T : AbstractContainerItem {
44 public void RegisterContainerElement<T>(string name) where T : AbstractContainerItem {
45 RegisterContainerElement(typeof(T), name);
45 RegisterContainerElement(typeof(T), name);
46 }
46 }
47
47
48 public ContainerElement LoadFile(string file) {
48 public ContainerElement LoadFile(string file) {
49 using (var reader = XmlReader.Create(file)) {
49 using (var reader = XmlReader.Create(file)) {
50 return (ContainerElement)Serializer.Deserialize(reader);
50 return (ContainerElement)Serializer.Deserialize(reader);
51 }
51 }
52 }
52 }
53
53
54 static ContainerConfigurationSchema CreateDefault() {
54 static ContainerConfigurationSchema CreateDefault() {
55 var schema = new ContainerConfigurationSchema();
55 var schema = new ContainerConfigurationSchema();
56
56
57 schema.RegisterContainerElement<RegisterElement>("register");
57 schema.RegisterContainerElement<RegisterElement>("register");
58 schema.RegisterContainerElement<FactoryElement>("factory");
58 schema.RegisterContainerElement<SerializedElement>("serialized");
59 schema.RegisterContainerElement<SerializedElement>("serialized");
59 schema.RegisterContainerElement<ValueElement>("value");
60 schema.RegisterContainerElement<ValueElement>("value");
60 schema.RegisterContainerElement<IncludeElement>("include");
61 schema.RegisterContainerElement<IncludeElement>("include");
61 schema.RegisterContainerElement<AssemblyElement>("assembly");
62 schema.RegisterContainerElement<AssemblyElement>("assembly");
62 schema.RegisterContainerElement<NamespaceElement>("namespace");
63 schema.RegisterContainerElement<NamespaceElement>("namespace");
63
64
64 return schema;
65 return schema;
65 }
66 }
66
67
67
68
68 }
69 }
69 } No newline at end of file
70 }
@@ -1,13 +1,13
1 namespace Implab.ServiceHost.Unity
1 namespace Implab.ServiceHost.Unity
2 {
2 {
3 public class DefaultParameterElement : InjectionParameterElement {
3 public class DefaultParameterElement : InjectionParameterElement {
4 public string Value {
4 public string Value {
5 get { return null; }
5 get { return null; }
6 }
6 }
7
7
8 public override void Visit(InjectionValueBuilder builder) {
8 public override void Visit(InjectionParameterBuilder builder) {
9 var type = builder.ResolveInjectedValueType(TypeName);
9 var type = builder.ResolveInjectedValueType(TypeName);
10 builder.SetValue(type, Safe.CreateDefaultValue(type));
10 builder.SetValue(type, Safe.CreateDefaultValue(type));
11 }
11 }
12 }
12 }
13 } No newline at end of file
13 }
@@ -1,17 +1,17
1 using System.Xml.Serialization;
1 using System.Xml.Serialization;
2
2
3 namespace Implab.ServiceHost.Unity {
3 namespace Implab.ServiceHost.Unity {
4 public class DependencyParameterElement : InjectionParameterElement {
4 public class DependencyParameterElement : InjectionParameterElement {
5
5
6 [XmlAttribute("name")]
6 [XmlAttribute("name")]
7 public string DependencyName { get; set; }
7 public string DependencyName { get; set; }
8
8
9 [XmlAttribute("optional")]
9 [XmlAttribute("optional")]
10 public bool Optional { get; set; }
10 public bool Optional { get; set; }
11
11
12 public override void Visit(InjectionValueBuilder builder) {
12 public override void Visit(InjectionParameterBuilder builder) {
13 var type = builder.ResolveInjectedValueType(TypeName);
13 var type = builder.ResolveInjectedValueType(TypeName);
14 builder.SetDependencyReference(type, DependencyName, Optional);
14 builder.SetDependencyReference(type, DependencyName, Optional);
15 }
15 }
16 }
16 }
17 } No newline at end of file
17 }
@@ -1,36 +1,54
1 using System;
1 using System;
2 using Implab.Components;
2 using Implab.Components;
3 using Unity;
3 using Unity;
4 using Unity.Injection;
4 using Unity.Injection;
5 using Unity.Registration;
5 using Unity.Registration;
6
6
7 namespace Implab.ServiceHost.Unity
7 namespace Implab.ServiceHost.Unity
8 {
8 {
9 public class FactoryRegistrationBuilder : RegistrationBuilder {
9 public class FactoryRegistrationBuilder : RegistrationBuilder {
10
10
11 internal InjectionMember Factory { get; private set; }
11 internal InjectionMember Factory { get; private set; }
12
12
13 internal FactoryRegistrationBuilder(Type registrationType) : base(registrationType) {
13 internal FactoryRegistrationBuilder(Type registrationType) : base(registrationType) {
14 }
14 }
15
15
16 /// <summary>
17 /// Задает делегат, который будет использоваться в качестве фабрики
18 /// для создания экземпляров, параметры делагата будет заполнены
19 /// соответствующими зависимостями.
20 /// </summary>
21 /// <param name="factory">Фабрика для создания экземпляров.</param>
16 public void SetFactoryDelegate(Delegate factory) {
22 public void SetFactoryDelegate(Delegate factory) {
17 Safe.ArgumentNotNull(factory, nameof(factory));
23 Safe.ArgumentNotNull(factory, nameof(factory));
18
24
19 Factory = new DelegateInjectionFactory(factory);
25 Factory = new DelegateInjectionFactory(factory);
20 }
26 }
21
27
28 /// <summary>
29 /// Указывает зависимость типа <typeparamref name="T"/> с именем
30 /// <paramref name="dependencyName"/>, которая будет передана в качетве
31 /// параметра делегату <paramref name="factory"/>
32 /// </summary>
33 /// <param name="dependencyName">Имя зависимости</param>
34 /// <param name="factory">Фабрика для создания экземпляра</param>
22 public void SetFactoryDependency<T>(string dependencyName, Func<T, object> factory) {
35 public void SetFactoryDependency<T>(string dependencyName, Func<T, object> factory) {
23 Safe.ArgumentNotNull(factory, nameof(factory));
36 Safe.ArgumentNotNull(factory, nameof(factory));
24
37
25 Factory = new InjectionFactory((c,t,name) => {
38 Factory = new InjectionFactory((c,t,name) => {
26 var backend = c.Resolve<T>(dependencyName);
39 var backend = c.Resolve<T>(dependencyName);
27 return factory(backend);
40 return factory(backend);
28 });
41 });
29 }
42 }
30
43
44 /// <summary>
45 /// Указывает зависимость, реализующую интерфейс <see cref="IFactory{TObj}"/>,
46 /// которая будет использоваться в качестве фабрики для создания объектов
47 /// </summary>
48 /// <param name="dependencyName"></param>
31 public void SetFactoryDependency<TFac, TObj>(string dependencyName) where TFac : IFactory<TObj> {
49 public void SetFactoryDependency<TFac, TObj>(string dependencyName) where TFac : IFactory<TObj> {
32
50
33 Factory = new InjectionFactory(c => c.Resolve<TFac>(dependencyName).Create());
51 Factory = new InjectionFactory(c => c.Resolve<TFac>(dependencyName).Create());
34 }
52 }
35 }
53 }
36 } No newline at end of file
54 }
@@ -1,13 +1,13
1 using System.Xml.Serialization;
1 using System.Xml.Serialization;
2
2
3 namespace Implab.ServiceHost.Unity {
3 namespace Implab.ServiceHost.Unity {
4 [XmlRoot("include", Namespace = Schema.ContainerConfigurationNamespace)]
4 [XmlRoot("include", Namespace = Schema.ContainerConfigurationNamespace)]
5 public class IncludeElement : AbstractContainerItem {
5 public class IncludeElement : AbstractContainerItem {
6 [XmlAttribute("href")]
6 [XmlAttribute("href")]
7 public string Href { get; set; }
7 public string Href { get; set; }
8
8
9 public override void Visit(ContainerBuilder context) {
9 public override void Visit(ContainerBuilder builder) {
10 context.Visit(this);
10 builder.Include(Href);
11 }
11 }
12 }
12 }
13 } No newline at end of file
13 }
@@ -1,12 +1,12
1 using System;
1 using System;
2 using System.Xml.Serialization;
2 using System.Xml.Serialization;
3
3
4 namespace Implab.ServiceHost.Unity {
4 namespace Implab.ServiceHost.Unity {
5 public abstract class InjectionParameterElement {
5 public abstract class InjectionParameterElement {
6
6
7 [XmlAttribute("type")]
7 [XmlAttribute("type")]
8 public string TypeName { get; set; }
8 public string TypeName { get; set; }
9
9
10 public abstract void Visit(InjectionValueBuilder builder);
10 public abstract void Visit(InjectionParameterBuilder builder);
11 }
11 }
12 } No newline at end of file
12 }
@@ -1,89 +1,92
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.ComponentModel;
3 using System.ComponentModel;
4 using System.Linq;
4 using System.Linq;
5 using System.Xml.Serialization;
5 using System.Xml.Serialization;
6 using Unity.Injection;
6 using Unity.Injection;
7
7
8 namespace Implab.ServiceHost.Unity {
8 namespace Implab.ServiceHost.Unity {
9
9
10 public class InjectionValueBuilder {
10 public class InjectionParameterBuilder {
11
11
12 readonly TypeResolver m_resolver;
12 readonly TypeResolver m_resolver;
13
13
14 public Type DefaultType { get; private set; }
14 public Type DefaultType { get; private set; }
15
15
16 public Type ValueType { get; private set; }
16 public Type ValueType { get; private set; }
17
17
18 public object Value { get; set; }
18 public object Value { get; set; }
19
19
20 internal InjectionParameterValue Injection {
20 internal InjectionParameterValue Injection {
21 get {
21 get {
22 if (Value != null)
22 if (Value != null)
23 return InjectionParameterValue.ToParameter(Value);
23 return InjectionParameterValue.ToParameter(Value);
24
24
25 return new InjectionParameter(ValueType, null);
25 return new InjectionParameter(ValueType, null);
26 }
26 }
27 }
27 }
28
28
29 internal InjectionValueBuilder(TypeResolver resolver, Type defaultType) {
29 internal InjectionParameterBuilder(TypeResolver resolver, Type defaultType) {
30 m_resolver = resolver;
30 m_resolver = resolver;
31 DefaultType = defaultType;
31 DefaultType = defaultType;
32 }
32 }
33
33
34 public Type ResolveInjectedValueType(string typeSpec) {
34 public Type ResolveInjectedValueType(string typeSpec) {
35 if (string.IsNullOrEmpty(typeSpec)) {
35 if (string.IsNullOrEmpty(typeSpec)) {
36 if (DefaultType == null)
36 if (DefaultType == null)
37 throw new Exception("The type must be specified");
37 throw new Exception("The type must be specified");
38 return DefaultType;
38 return DefaultType;
39 }
39 }
40 return m_resolver.Resolve(typeSpec);
40 return m_resolver.Resolve(typeSpec, true);
41 }
41 }
42
42
43 public Type ResolveType(string typeSpec) {
43 public Type ResolveType(string typeSpec) {
44 return m_resolver.Resolve(typeSpec);
44 return m_resolver.Resolve(typeSpec, true);
45 }
45 }
46
46
47 public void SetValue(Type type, object value) {
47 public void SetValue(Type type, object value) {
48 ValueType = type;
48 ValueType = type;
49 Value = value;
49 Value = value;
50 }
50 }
51
51
52 public void SetValue<T>(T value) {
52 public void SetValue<T>(T value) {
53 SetValue(typeof(T), value);
53 SetValue(typeof(T), value);
54 }
54 }
55
55
56 public void SetDependencyReference(Type type, string name, bool optional) {
56 public void SetDependencyReference(Type type, string name, bool optional) {
57 ValueType = type;
57 ValueType = type;
58 Value = optional ? (object)new OptionalParameter(type, name) : new ResolvedParameter(type, name);
58 Value = optional ? (object)new OptionalParameter(type, name) : new ResolvedParameter(type, name);
59 }
59 }
60
60
61 internal void Visit(ArrayParameterElement arrayParameter) {
61 internal void Visit(ArrayParameterElement arrayParameter) {
62 Type itemsType = null;
62 Type itemsType = null;
63 var arrayType = string.IsNullOrEmpty(arrayParameter.TypeName) ? null : ResolveType(arrayParameter.TypeName);
63 var arrayType = string.IsNullOrEmpty(arrayParameter.TypeName) ? null : ResolveType(arrayParameter.TypeName);
64
64
65 if (!string.IsNullOrEmpty(arrayParameter.ItemsType)) {
65 if (!string.IsNullOrEmpty(arrayParameter.ItemsType)) {
66 itemsType = ResolveType(arrayParameter.ItemsType);
66 itemsType = ResolveType(arrayParameter.ItemsType);
67 if (arrayType == null)
67 if (arrayType == null)
68 arrayType = itemsType.MakeArrayType();
68 arrayType = itemsType.MakeArrayType();
69 } else {
69 } else {
70 itemsType = arrayType?.GetInterface(typeof(IEnumerable<>).FullName)?.GetGenericArguments()[0];
70 itemsType = arrayType?.GetInterface(typeof(IEnumerable<>).FullName)?.GetGenericArguments()[0];
71 }
71 }
72
72
73 if (itemsType == null)
73 if (itemsType == null)
74 throw new Exception("Failed to determine array elements type");
74 throw new Exception("Failed to determine array elements type");
75
75
76 InjectionParameterValue[] injections = (arrayParameter.Items ?? new InjectionParameterElement[0])
76 InjectionParameterValue[] injections = (arrayParameter.Items ?? new InjectionParameterElement[0])
77 .Select(x => {
77 .Select(x => {
78 var builder = new InjectionValueBuilder(m_resolver, itemsType);
78 var builder = new InjectionParameterBuilder(m_resolver, itemsType);
79 x.Visit(builder);
79 x.Visit(builder);
80 return builder.Injection;
80 return builder.Injection;
81 })
81 })
82 .ToArray();
82 .ToArray();
83
83
84 var array = itemsType.IsGenericParameter ? (object)new GenericResolvedArrayParameter(itemsType.Name, injections) : new ResolvedArrayParameter(itemsType, injections);
84 var array = itemsType.IsGenericParameter ?
85 (object)new GenericResolvedArrayParameter(itemsType.Name, injections) :
86 new ResolvedArrayParameter(itemsType, injections);
87
85 ValueType = arrayType;
88 ValueType = arrayType;
86 Value = array;
89 Value = array;
87 }
90 }
88 }
91 }
89 } No newline at end of file
92 }
@@ -1,13 +1,13
1 using System;
1 using System;
2
2
3 namespace Implab.ServiceHost.Unity
3 namespace Implab.ServiceHost.Unity
4 {
4 {
5 public class InstanceRegistrationBuilder : RegistrationBuilder {
5 public class InstanceRegistrationBuilder : RegistrationBuilder {
6
6
7 public InjectionValueBuilder ValueBuilder { get; private set; }
7 public InjectionParameterBuilder ValueBuilder { get; private set; }
8
8
9 internal InstanceRegistrationBuilder(TypeResolver typeResolver, Type registrationType) : base(registrationType) {
9 internal InstanceRegistrationBuilder(TypeResolver typeResolver, Type registrationType) : base(registrationType) {
10 ValueBuilder = new InjectionValueBuilder(typeResolver, registrationType);
10 ValueBuilder = new InjectionParameterBuilder(typeResolver, registrationType);
11 }
11 }
12 }
12 }
13 } No newline at end of file
13 }
@@ -1,15 +1,15
1 using System.Xml.Serialization;
1 using System.Xml.Serialization;
2
2
3 namespace Implab.ServiceHost.Unity
3 namespace Implab.ServiceHost.Unity
4 {
4 {
5 [XmlRoot("namespace", Namespace = Schema.ContainerConfigurationNamespace)]
5 [XmlRoot("namespace", Namespace = Schema.ContainerConfigurationNamespace)]
6 public class NamespaceElement : AbstractContainerItem {
6 public class NamespaceElement : AbstractContainerItem {
7
7
8 [XmlAttribute("name")]
8 [XmlAttribute("name")]
9 public string Name { get; set; }
9 public string Name { get; set; }
10
10
11 public override void Visit(ContainerBuilder context) {
11 public override void Visit(ContainerBuilder builder) {
12 context.Visit(this);
12 builder.AddNamespace(Name);
13 }
13 }
14 }
14 }
15 } No newline at end of file
15 }
@@ -1,33 +1,33
1 using System;
1 using System;
2 using System.Xml;
2 using System.Xml;
3 using System.Xml.Schema;
3 using System.Xml.Schema;
4 using System.Xml.Serialization;
4 using System.Xml.Serialization;
5
5
6 namespace Implab.ServiceHost.Unity
6 namespace Implab.ServiceHost.Unity
7 {
7 {
8 public class SerializedParameterElement : InjectionParameterElement {
8 public class SerializedParameterElement : InjectionParameterElement {
9 [XmlAttribute("href")]
9 [XmlAttribute("href")]
10 public string Location { get; set; }
10 public string Location { get; set; }
11
11
12 [XmlAnyElement]
12 [XmlAnyElement]
13 public XmlElement[] Content { get; set; }
13 public XmlElement[] Content { get; set; }
14
14
15 public XmlReader GetReader() {
15 public XmlReader GetReader() {
16 if (!string.IsNullOrEmpty(Location))
16 if (!string.IsNullOrEmpty(Location))
17 return XmlReader.Create(Location);
17 return XmlReader.Create(Location);
18 if (Content != null && Content.Length > 0)
18 if (Content != null && Content.Length > 0)
19 return Content[0].CreateNavigator().ReadSubtree();
19 return Content[0].CreateNavigator().ReadSubtree();
20
20
21 throw new Exception("No content found, expected XML document");
21 throw new Exception("No content found, expected XML document");
22 }
22 }
23
23
24 public override void Visit(InjectionValueBuilder builder) {
24 public override void Visit(InjectionParameterBuilder builder) {
25 var type = builder.ResolveInjectedValueType(TypeName);
25 var type = builder.ResolveInjectedValueType(TypeName);
26
26
27 var serializer = new XmlSerializer(type);
27 var serializer = new XmlSerializer(type);
28 using(var reader = GetReader())
28 using(var reader = GetReader())
29 builder.SetValue(type, serializer.Deserialize(reader));
29 builder.SetValue(type, serializer.Deserialize(reader));
30
30
31 }
31 }
32 }
32 }
33 } No newline at end of file
33 }
@@ -1,58 +1,182
1 using System;
1 using System;
2 using System.Linq;
2 using System.Linq;
3 using System.Text;
3 using System.Text;
4
4
5 namespace Implab.ServiceHost.Unity {
5 namespace Implab.ServiceHost.Unity {
6 public class TypeReference {
6 /// <summary>
7 public string TypeName { get; set; }
7 /// Ссылка на тип, является абстрактной записью имени CLR типа.
8
8 /// </summary>
9 public string Namespace { get; set; }
9 /// <remarks>
10
10 /// Ссылка на тип содержит сокращенную информацию о типе и для ее интерпретации
11 public TypeReference[] GenericParameters { get; set; }
11 /// требуется некоторый контекст, который позволит превратить ее в полноценный
12
12 /// <see cref="Type"/>. Ссылки на тип позволяют записать:
13 public bool IsArray { get; set; }
13 /// <list>
14 /// <item><description>общие типы, их специализации</description></item>
15 /// <item><description>вложенные типы</description></item>
16 /// <item><description>массивы</description></item>
17 /// </list>
18 /// <para>
19 /// Для получения из ссылки на тип конкретного CLR типа используется <see cref="TypeResolver.Resolve(TypeReference, bool)"/>.
20 /// </para>
21 /// <para>
22 /// Ссылку на тип можно создать либо програмно при помощи методов <see cref="Create(string, string, int)"/>,
23 /// <see cref="Create(string, int)"/>, <see cref="MakeArrayType(int)"/>, <see cref="MakeGenericType(TypeReference[])"/>,
24 /// либо разобрав строку со спецификацией при помощи метода <see cref="Parse(string)"/>.
25 /// </para>
26 /// <para>
27 /// Спецификация ссыдки на тип имеет следующий вид <c>Name.Space.MyType+Nested{String}[][]</c>, где:
28 /// <list type="table">
29 /// <item>
30 /// <term><c>.</c></term>
31 /// <description>Разделяет элементы пространства имен</description>
32 /// <item>
33 /// <item>
34 /// <term><c>+</c></term>
35 /// <description>Разделяет вложенные типы</description>
36 /// <item>
37 /// <item>
38 /// <term><c>[]</c>, <c>[,,,]</c></term>
39 /// <description>Указывает на то, что тип является массивом, также указывается его размерность</description>
40 /// <item>
41 /// <item>
42 /// <term><c>{}</c>, <c>{,,}</c>, <c>{Int32,String}</c></term>
43 /// <description>Указывает на то, что тип является общим, также
44 /// указывается количество параметров, либо конкретные типы для
45 /// специализации</description>
46 /// <item>
47 /// </list>
48 /// </para>
49 /// </remarks>
50 public abstract class TypeReference {
14
51
15 public bool IsOpenGeneric {
52 /// <summary>
53 /// Имя типа без дополнительных элементов, указывающих на то, что он общий или массив.
54 /// </summary>
55 /// <remarks>
56 /// Для массивов это имя его элементов.
57 /// </remarks>
58 public abstract string Name { get; }
59
60 /// <summary>
61 /// Пространство имен в котором нахожится тип.
62 /// </summary>
63 /// <remarks>
64 /// Для вложенных типов это пространтство имен типа самого верхнего уровня,
65 /// для массивов - пространство имен его элементов.
66 /// </remarks>
67 public abstract string Namespace { get; }
68
69 /// <summary>
70 /// Количество параметров общего типа.
71 /// </summary>
72 /// <remarks>
73 /// <para>
74 /// Вложенные типы неявно получают параметры от типов в которых они объявлены,
75 /// данное свойство это не учитывает, возвращается только количество собственных
76 /// параметров.
77 /// </para>
78 /// <para>
79 /// Данное свойство используется для получения CRL имени типа.
80 /// </para>
81 /// </remarks>
82 public abstract int GenericParametersCount { get; }
83
84 public virtual string ClrName {
16 get {
85 get {
17 return GenericParameters!=null && GenericParameters.Contains(null);
86 return GenericParametersCount != 0 ? $"{Name}`{GenericParametersCount}" : Name;
18 }
19 }
20
21 public bool IsGeneric {
22 get {
23 return GenericParameters != null && GenericParameters.Length > 0;
24 }
87 }
25 }
88 }
26
89
90 /// <summary>
91 /// Создает ссылку на специализацию текущего типа.
92 /// </summary>
93 /// <param name="genericParameters">Ссылки на типы, которые будут использоваться для специализации текущего типа.</param>
94 /// <returns>Специализация данного типа.</returns>
95 public virtual SpecializedTypeReference MakeGenericType(TypeReference[] genericParameters) {
96 if (GenericParametersCount == 0)
97 throw new InvalidOperationException("Can't specialize a non-geneic type");
98
99 if (genericParameters == null || GenericParametersCount != genericParameters.Length)
100 throw new InvalidOperationException("Generic parameters count mismatch");
101
102 return new SpecializedTypeReference(this, genericParameters);
103 }
104
105 /// <summary>
106 /// Создает ссылку на тип массива указанной размерности, элементами которого являются экземпаляры даннго типа.
107 /// </summary>
108 /// <param name="rank">Размерность, если размерность <c>1</c> создается вектор (<see cref="Type.MakeArrayType()"/>).</param>
109 /// <returns>Ссылка на тип массива</returns>
110 public ArrayTypeReference MakeArrayType(int rank) {
111 Safe.ArgumentInRange(rank > 0, nameof(rank));
112
113 return new ArrayTypeReference(this, rank);
114 }
115
116 /// <summary>
117 /// Создает ссылку на вложенный тип.
118 /// </summary>
119 /// <param name="name">Имя типа</param>
120 /// <param name="genericParameters">Количество параметров, если это общий тип, иначе 0.</param>
121 /// <returns>Ссылка на вложенный тип.</returns>
122 public TypeReference Create(string name, int genericParameters) {
123 Safe.ArgumentNotEmpty(name, nameof(name));
124 Safe.ArgumentInRange(genericParameters >= 0, nameof(genericParameters));
125
126 return new NestedTypeReference(this, name, genericParameters);
127 }
128
129 /// <summary>
130 /// Возвращает строковое представление ссылки на тип.
131 /// </summary>
132 /// <returns></returns>
27 public override string ToString() {
133 public override string ToString() {
28 var builder = new StringBuilder();
134 var builder = new StringBuilder();
29
135 WriteTypeName(builder);
30 if (!string.IsNullOrEmpty(Namespace)) {
136 WriteTypeParams(builder);
31 builder.Append(Namespace);
32 builder.Append('.');
33 }
34
35 if (!string.IsNullOrEmpty(TypeName)) {
36 builder.Append(TypeName);
37 } else {
38 builder.Append("__unnamed__");
39 }
40
41 if (GenericParameters != null && GenericParameters.Length > 0) {
42 builder.Append('{');
43 for(var i = 0; i < GenericParameters.Length; i++) {
44 if (i > 0)
45 builder.Append(',');
46 builder.Append(GenericParameters[i]);
47 }
48 builder.Append('}');
49 }
50
51 return builder.ToString();
137 return builder.ToString();
52 }
138 }
53 public static TypeReference Parse(string text) {
139
54 var parser = new TypeReferenceParser(text);
140 internal virtual void WriteTypeName(StringBuilder builder) {
141 if (!string.IsNullOrEmpty(Namespace))
142 builder
143 .Append(Namespace)
144 .Append('.');
145 builder.Append(Name);
146 }
147
148 internal virtual void WriteTypeParams(StringBuilder builder) {
149 if (GenericParametersCount > 0)
150 builder
151 .Append('{')
152 .Append(',', GenericParametersCount-1)
153 .Append('}');
154 }
155
156 internal abstract void Visit(TypeResolutionContext visitor);
157
158 /// <summary>
159 /// Создает ссылку на тип.
160 /// </summary>
161 /// <param name="ns">Пространство имен, либо его фрагмент.</param>
162 /// <param name="name">Имя типа без указания на количество параметров, либо на то, что это массив.</param>
163 /// <param name="genericParameters">Количество параметров типа, если это общий тип, иначе 0.</param>
164 /// <returns>Ссылка на тип.</returns>
165 public static TypeReference Create(string ns, string name, int genericParameters) {
166 Safe.ArgumentNotEmpty(name, nameof(name));
167 Safe.ArgumentInRange(genericParameters >= 0, nameof(genericParameters));
168 return new RootTypeReference(ns, name, genericParameters);
169 }
170
171 /// <summary>
172 /// Разирает строковую запись ссылки на тип.
173 /// </summary>
174 /// <param name="typeSpec">Строковая запись ссылки на тип, например <c>Dictionary{String,String}</c></param>
175 /// <returns>Ссылка на тип.</returns>
176 public static TypeReference Parse(string typeSpec) {
177 var parser = new TypeReferenceParser(typeSpec);
55 return parser.Parse();
178 return parser.Parse();
56 }
179 }
180
57 }
181 }
58 } No newline at end of file
182 }
@@ -1,175 +1,245
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Text.RegularExpressions;
4 using System.Text.RegularExpressions;
4
5
5 namespace Implab.ServiceHost.Unity {
6 namespace Implab.ServiceHost.Unity {
6 internal class TypeReferenceParser {
7 internal class TypeReferenceParser {
7 enum TokenType {
8 enum TokenType {
8 None,
9 None,
9
10
10 Word,
11 Word,
11
12
12 Dot,
13 Dot,
13
14
14 Comma,
15 Comma,
15
16
16 OpenList,
17 OpenList,
17
18
18 CloseList,
19 CloseList,
19
20
20 OpenArray,
21 OpenArray,
21
22
22 CloseArray,
23 CloseArray,
23
24
25 Plus,
26
24 Eof
27 Eof
25 }
28 }
26
29
27 readonly Regex _tokens = new Regex(@"([\w\+]+)|\s*([\.{},\[\]])\s*");
30 readonly Regex _tokens = new Regex(@"\G(?:([\w]+)|\s*([\+\.{},\[\]])\s*)", RegexOptions.Compiled);
28
31
29 TokenType m_token;
32 TokenType m_token;
30
33
31 string m_tokenValue;
34 string m_tokenValue;
32
35
33 int m_pos;
36 int m_pos;
34
37
35 int m_tokenPos;
38 int m_tokenPos;
36
39
37 readonly string m_text;
40 readonly string m_text;
38
41
39 TokenType Token { get { return m_token; } }
42 TokenType Token { get { return m_token; } }
40
43
41 string TokenValue { get { return m_tokenValue; } }
44 string TokenValue { get { return m_tokenValue; } }
42
45
43 int TokenPos { get { return m_tokenPos; } }
46 int TokenPos { get { return m_tokenPos; } }
44
47
45 public TypeReferenceParser(string text) {
48 public TypeReferenceParser(string text) {
46 Safe.ArgumentNotEmpty(text, nameof(text));
49 Safe.ArgumentNotEmpty(text, nameof(text));
47 m_text = text;
50 m_text = text;
48 }
51 }
49
52
50 bool ReadToken() {
53 bool ReadToken() {
51 if (m_pos >= m_text.Length) {
54 if (m_pos >= m_text.Length) {
52 m_token = TokenType.Eof;
55 m_token = TokenType.Eof;
53 m_tokenValue = null;
56 m_tokenValue = null;
54 return false;
57 return false;
55 }
58 }
56
59
57 var m = _tokens.Match(m_text, m_pos);
60 var m = _tokens.Match(m_text, m_pos);
58
61
59 if (m.Success) {
62 if (m.Success) {
60 m_tokenPos = m_pos;
63 m_tokenPos = m_pos;
61 m_pos += m.Length;
64 m_pos += m.Length;
62 if (m.Groups[1].Success) {
65 if (m.Groups[1].Success) {
63 m_token = TokenType.Word;
66 m_token = TokenType.Word;
64 m_tokenValue = m.Groups[1].Value;
67 m_tokenValue = m.Groups[1].Value;
65 } else if (m.Groups[2].Success) {
68 } else if (m.Groups[2].Success) {
66 m_tokenValue = null;
69 m_tokenValue = null;
67 switch (m.Groups[2].Value) {
70 switch (m.Groups[2].Value) {
68 case "{":
71 case "{":
69 m_token = TokenType.OpenList;
72 m_token = TokenType.OpenList;
70 break;
73 break;
71 case "}":
74 case "}":
72 m_token = TokenType.CloseList;
75 m_token = TokenType.CloseList;
73 break;
76 break;
74 case ".":
77 case ".":
75 m_token = TokenType.Dot;
78 m_token = TokenType.Dot;
76 break;
79 break;
77 case ",":
80 case ",":
78 m_token = TokenType.Comma;
81 m_token = TokenType.Comma;
79 break;
82 break;
80 case "[":
83 case "[":
81 m_token = TokenType.OpenArray;
84 m_token = TokenType.OpenArray;
82 break;
85 break;
83 case "]":
86 case "]":
84 m_token = TokenType.CloseArray;
87 m_token = TokenType.CloseArray;
85 break;
88 break;
89 case "+":
90 m_token = TokenType.Plus;
91 break;
86 }
92 }
87 }
93 }
88 return true;
94 return true;
89 }
95 }
90 throw new FormatException($"Failed to parse '{m_text}' at pos {m_pos}");
96 throw new FormatException($"Failed to parse '{m_text}' at pos {m_pos}");
91 }
97 }
92
98
93 public TypeReference Parse() {
99 public TypeReference Parse() {
94 var result = ReadTypeReference();
100 var result = ReadTypeReference();
95 if (Token != TokenType.Eof)
101 if (Token != TokenType.Eof)
96 ThrowUnexpectedToken();
102 ThrowUnexpectedToken();
97 return result;
103 return result;
98 }
104 }
99
105
100 string[] ReadTypeName() {
106 string[] ReadQTypeName() {
101 var parts = new List<string>();
107 var parts = new List<string>();
102
108
103 string current = null;
109 string current = null;
104 bool stop = false;
110 bool stop = false;
105 while ((!stop) && ReadToken()) {
111 while ((!stop) && ReadToken()) {
106 switch (Token) {
112 switch (Token) {
107 case TokenType.Word:
113 case TokenType.Word:
108 if (current != null)
114 if (current != null)
109 ThrowUnexpectedToken();
115 ThrowUnexpectedToken();
110 current = TokenValue;
116 current = TokenValue;
111 break;
117 break;
112 case TokenType.Dot:
118 case TokenType.Dot:
113 if (current == null)
119 if (current == null)
114 ThrowUnexpectedToken();
120 ThrowUnexpectedToken();
115 parts.Add(current);
121 parts.Add(current);
116 current = null;
122 current = null;
117 break;
123 break;
118 default:
124 default:
119 stop = true;
125 stop = true;
120 break;
126 break;
121 }
127 }
122 }
128 }
123 if (current != null)
129 if (current != null)
124 parts.Add(current);
130 parts.Add(current);
125
131
126 if (parts.Count == 0)
132 if (parts.Count == 0)
127 return null;
133 return null;
128
134
129 return parts.ToArray();
135 return parts.ToArray();
130 }
136 }
131
137
138 string ReadNQTypeName() {
139 ReadToken();
140 if (Token != TokenType.Word)
141 ThrowUnexpectedToken();
142 return TokenValue;
143 }
144
132 TypeReference ReadTypeReference() {
145 TypeReference ReadTypeReference() {
133
146
134 var parts = ReadTypeName();
147 var parts = ReadQTypeName();
135 if (parts == null)
148 if (parts == null)
136 return null;
149 return null;
137
150
138 var typeReference = new TypeReference {
151 var genericParameters = ReadGenericParams();
139 Namespace = string.Join(".", parts, 0, parts.Length - 1),
152
140 TypeName = parts[parts.Length - 1]
153 var typeReference = TypeReference.Create(
141 };
154 string.Join(".", parts, 0, parts.Length - 1),
155 parts[parts.Length - 1],
156 genericParameters.Length
157 );
158
159 if (genericParameters.Length > 0 && genericParameters.All(x => x != null))
160 typeReference = typeReference.MakeGenericType(genericParameters);
161
162 typeReference = ReadArraySpec(typeReference);
163
164 if(Token == TokenType.Plus)
165 return ReadNestedType(typeReference);
166
167 return typeReference;
168 }
169
170 TypeReference ReadNestedType(TypeReference declaringType) {
171 var name = ReadNQTypeName();
172 if(string.IsNullOrEmpty(name))
173 throw new FormatException("Nested type name can't be empty");
174 ReadToken();
175
176 var genericParameters = ReadGenericParams();
177
178 var typeReference = declaringType.Create(
179 name,
180 genericParameters.Length
181 );
142
182
143 switch (Token) {
183 if (genericParameters.Length > 0 && genericParameters.All(x => x != null))
144 case TokenType.OpenList:
184 typeReference = typeReference.MakeGenericType(genericParameters);
145 typeReference.GenericParameters = ReadTypeReferenceList();
185
146 if (Token != TokenType.CloseList)
186 typeReference = ReadArraySpec(typeReference);
147 ThrowUnexpectedToken();
187
148 ReadToken();
188 if(Token == TokenType.Plus)
149 break;
189 return ReadNestedType(typeReference);
190
191 return typeReference;
192 }
193
194 TypeReference[] ReadGenericParams() {
195 if (Token == TokenType.OpenList) {
196 var genericParameters = ReadTypeReferenceList();
197 if (Token != TokenType.CloseList)
198 ThrowUnexpectedToken();
199 ReadToken();
200
201 return genericParameters;
202 }
203
204 return Array.Empty<TypeReference>();
205 }
206
207 TypeReference ReadArraySpec(TypeReference typeReference) {
208 while (Token == TokenType.OpenArray) {
209 var rank = CountRank();
210 if (Token != TokenType.CloseArray)
211 ThrowUnexpectedToken();
212
213 typeReference = typeReference.MakeArrayType(rank);
214
215 ReadToken();
150 }
216 }
151
217
152 return typeReference;
218 return typeReference;
153 }
219 }
154
220
155 int CountDimentions() {
221 int CountRank() {
156 return 0;
222 int rank = 0;
223 do {
224 rank++;
225 } while(ReadToken() && Token == TokenType.Comma);
226 return rank;
157 }
227 }
158
228
159 TypeReference[] ReadTypeReferenceList() {
229 TypeReference[] ReadTypeReferenceList() {
160 var list = new List<TypeReference>();
230 var list = new List<TypeReference>();
161
231
162 do {
232 do {
163 var typeReference = ReadTypeReference();
233 var typeReference = ReadTypeReference();
164 list.Add(typeReference);
234 list.Add(typeReference);
165 } while (Token == TokenType.Comma);
235 } while (Token == TokenType.Comma);
166
236
167 return list.ToArray();
237 return list.ToArray();
168 }
238 }
169
239
170 void ThrowUnexpectedToken() {
240 void ThrowUnexpectedToken() {
171 throw new FormatException($"Unexpected '{Token}' at pos {TokenPos}: -->{m_text.Substring(TokenPos, Math.Min(m_text.Length - TokenPos, 10))}");
241 throw new FormatException($"Unexpected '{Token}' at pos {TokenPos}: -->{m_text.Substring(TokenPos, Math.Min(m_text.Length - TokenPos, 10))}");
172 }
242 }
173
243
174 }
244 }
175 } No newline at end of file
245 }
@@ -1,77 +1,75
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using Unity.Injection;
4 using Unity.Injection;
5 using Unity.Registration;
5 using Unity.Registration;
6
6
7 namespace Implab.ServiceHost.Unity {
7 namespace Implab.ServiceHost.Unity {
8 public class TypeRegistrationBuilder : RegistrationBuilder {
8 public class TypeRegistrationBuilder : RegistrationBuilder {
9
9
10 readonly TypeResolver m_resolver;
10 readonly TypeResolver m_resolver;
11
11
12 readonly List<InjectionMember> m_injections = new List<InjectionMember>();
12 readonly List<InjectionMember> m_injections = new List<InjectionMember>();
13
13
14 internal InjectionMember[] Injections { get { return m_injections.ToArray(); } }
14 internal InjectionMember[] Injections { get { return m_injections.ToArray(); } }
15
15
16 public Type ImplementationType {
16 public Type ImplementationType {
17 get;
17 get;
18 private set;
18 private set;
19 }
19 }
20
20
21 internal TypeRegistrationBuilder(TypeResolver resolver, Type registrationType, Type implementationType) : base(registrationType) {
21 internal TypeRegistrationBuilder(TypeResolver resolver, Type registrationType, Type implementationType) : base(registrationType) {
22 ImplementationType = implementationType;
22 ImplementationType = implementationType;
23
23
24 // when registering a generic mapping, register all generic parameter names as local types
24 // when registering a generic mapping, register all generic parameter names as local types
25 if (ImplementationType.IsGenericTypeDefinition) {
25 if (ImplementationType.IsGenericTypeDefinition) {
26 m_resolver = new TypeResolver(resolver);
26 m_resolver = new TypeResolver(resolver);
27
27
28 foreach (var p in ImplementationType.GetGenericArguments())
28 foreach (var p in ImplementationType.GetGenericArguments())
29 m_resolver.AddMapping(p.Name, p);
29 m_resolver.AddMapping(p.Name, p);
30 } else {
30 } else {
31 m_resolver = resolver;
31 m_resolver = resolver;
32 }
32 }
33 }
33 }
34
34
35 internal void Visit(ConstructorInjectionElement constructorInjection) {
35 internal void Visit(ConstructorInjectionElement constructorInjection) {
36
36
37
37
38 var parameters = constructorInjection.Parameters?
38 var parameters = constructorInjection.Parameters?
39 .Select(x => {
39 .Select(x => {
40 var valueBuilder = new InjectionValueBuilder(m_resolver, null);
40 var valueBuilder = new InjectionParameterBuilder(m_resolver, null);
41 x.Visit(valueBuilder);
41 x.Visit(valueBuilder);
42 return valueBuilder.Injection;
42 return valueBuilder.Injection;
43 })
43 })
44 .ToArray();
44 .ToArray();
45
45
46 var injection = parameters != null ? new InjectionConstructor(parameters) : new InjectionConstructor();
46 var injection = parameters != null ? new InjectionConstructor(parameters) : new InjectionConstructor();
47 m_injections.Add(injection);
47 m_injections.Add(injection);
48 }
48 }
49
49
50 internal void Visit(MethodInjectionElement methodInjection) {
50 internal void Visit(MethodInjectionElement methodInjection) {
51 var valueContext = new InjectionValueBuilder(m_resolver, null);
52
53 var parameters = methodInjection.Parameters?
51 var parameters = methodInjection.Parameters?
54 .Select(x => {
52 .Select(x => {
55 var valueBuilder = new InjectionValueBuilder(m_resolver, null);
53 var valueBuilder = new InjectionParameterBuilder(m_resolver, null);
56 x.Visit(valueBuilder);
54 x.Visit(valueBuilder);
57 return valueBuilder.Injection;
55 return valueBuilder.Injection;
58 })
56 })
59 .ToArray();
57 .ToArray();
60
58
61 var injection = parameters != null ? new InjectionMethod(methodInjection.Name, parameters) : new InjectionMethod(methodInjection.Name);
59 var injection = parameters != null ? new InjectionMethod(methodInjection.Name, parameters) : new InjectionMethod(methodInjection.Name);
62 m_injections.Add(injection);
60 m_injections.Add(injection);
63 }
61 }
64
62
65 internal void Visit(PropertyInjectionElement propertyInjection) {
63 internal void Visit(PropertyInjectionElement propertyInjection) {
66 if (propertyInjection.Value == null)
64 if (propertyInjection.Value == null)
67 throw new Exception($"A value value must be specified for the property '{propertyInjection.Name}'");
65 throw new Exception($"A value value must be specified for the property '{propertyInjection.Name}'");
68
66
69 var propertyType = RegistrationType.GetProperty(propertyInjection.Name)?.PropertyType;
67 var propertyType = ImplementationType.GetProperty(propertyInjection.Name)?.PropertyType;
70 var valueContext = new InjectionValueBuilder(m_resolver, propertyType);
68 var valueContext = new InjectionParameterBuilder(m_resolver, propertyType);
71
69
72 propertyInjection.Value.Visit(valueContext);
70 propertyInjection.Value.Visit(valueContext);
73 var injection = new InjectionProperty(propertyInjection.Name, valueContext.Injection);
71 var injection = new InjectionProperty(propertyInjection.Name, valueContext.Injection);
74 m_injections.Add(injection);
72 m_injections.Add(injection);
75 }
73 }
76 }
74 }
77 } No newline at end of file
75 }
@@ -1,125 +1,98
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5 using System.Text.RegularExpressions;
5 using System.Text.RegularExpressions;
6 using Implab.Diagnostics;
6 using Implab.Diagnostics;
7
7
8 namespace Implab.ServiceHost.Unity {
8 namespace Implab.ServiceHost.Unity {
9 using System.Diagnostics;
9 using static Trace<TypeResolver>;
10 using static Trace<TypeResolver>;
10 public class TypeResolver {
11 public class TypeResolver {
11 readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>();
12 readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>();
12
13
13 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
14 Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled);
14 readonly LinkedList<string> m_namespases = new LinkedList<string>();
15 readonly LinkedList<string> m_namespases = new LinkedList<string>();
15
16
17 internal Type Resolve(string ns, string typeName) {
18 var fullName = string.IsNullOrEmpty(ns) ? typeName : $"{ns}.{typeName}";
19
20 return ProbeInNamespaces(fullName);
21 }
22
23 public Type Resolve(TypeReference typeReference, bool throwOnFail) {
24 var context = new TypeResolutionContext(this, throwOnFail);
25 typeReference.Visit(context);
26 return context.MakeType();
27 }
28
29 public Type Resolve(string typeSpec, bool throwOnFail) {
30 var typeReference = TypeReference.Parse(typeSpec);
31 return Resolve(typeReference, throwOnFail);
32 }
33
16 LinkedListNode<string> m_insertAt;
34 LinkedListNode<string> m_insertAt;
17
35
18 readonly TypeResolver m_parent;
36 readonly TypeResolver m_parent;
19
37
20 public TypeResolver() : this(null) {
38 public TypeResolver() : this(null) {
21
22 }
39 }
23
40
24 public TypeResolver(TypeResolver parent) {
41 public TypeResolver(TypeResolver parent) {
25 m_parent = parent;
42 m_parent = parent;
26 m_insertAt = new LinkedListNode<string>(string.Empty);
43 m_insertAt = new LinkedListNode<string>(string.Empty);
27 m_namespases.AddFirst(m_insertAt);
44 m_namespases.AddFirst(m_insertAt);
28 }
45 }
29
46
30 public void AddNamespace(string ns) {
47 public void AddNamespace(string ns) {
31 Safe.ArgumentMatch(ns, nameof(ns), _nsRx);
48 Safe.ArgumentMatch(ns, nameof(ns), _nsRx);
32 if (m_insertAt != null)
49 if (m_insertAt != null)
33 m_namespases.AddAfter(m_insertAt, ns);
50 m_namespases.AddAfter(m_insertAt, ns);
34 else
51 else
35 m_namespases.AddFirst(ns);
52 m_namespases.AddFirst(ns);
36 }
53 }
37
54
38 public void AddMapping(string typeName, Type type) {
55 public void AddMapping(string typeName, Type type) {
39 Safe.ArgumentNotEmpty(typeName, nameof(typeName));
56 Safe.ArgumentNotEmpty(typeName, nameof(typeName));
40 Safe.ArgumentNotNull(type, nameof(type));
57 Safe.ArgumentNotNull(type, nameof(type));
41
58
42 m_cache[typeName] = type;
59 m_cache[typeName] = type;
43 }
60 }
44
61
45 public Type Resolve(TypeReference reference) {
62 Type ProbeInNamespaces(string localName) {
46 var args = reference.IsGeneric && !reference.IsOpenGeneric ? reference.GenericParameters?.Select(Resolve).ToArray() : null;
47 var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0;
48
63
49 Type resolved;
64 Type resolved;
50 if (!m_cache.TryGetValue(reference.ToString(), out resolved)) {
65 if (!m_cache.TryGetValue(localName, out resolved)) {
51 resolved = ResolveInternal(reference, args, argc);
66 foreach (var ns in m_namespases) {
52 if (resolved == null)
67 var typeName = string.IsNullOrEmpty(ns) ? localName : $"{ns}.{localName}";
53 throw new Exception($"Failed to resolve {reference}");
68 resolved = Probe(typeName);
54 m_cache[reference.ToString()] = resolved;
69 if (resolved != null) {
70 Log($"Probe '{localName}' -> '{resolved.FullName}'");
71 break;
72 }
73 }
74
75 if (resolved == null && m_parent != null)
76 resolved = m_parent.ProbeInNamespaces(localName);
77
78 if(resolved == null)
79 Log($"Probe '{localName}' failed");
80
81 m_cache[localName] = resolved;
55 }
82 }
56
83
57 return resolved;
84 return resolved;
58 }
85 }
59
86
60 public Type Resolve(string typeSpec) {
61 return Resolve(TypeReference.Parse(typeSpec));
62 }
63
64 Type ResolveInternal(TypeReference reference, Type[] args, int argc) {
65 var resolved = ProbeInNamespaces(
66 String.Join(".", new[] { reference.Namespace, reference.TypeName }.Where(x => !string.IsNullOrEmpty(x))),
67 args,
68 argc,
69 reference.IsArray,
70 reference.ToString()
71 );
72
73 if (resolved == null && m_parent != null)
74 resolved = m_parent.ResolveInternal(reference, args, argc);
75
76 return resolved;
77 }
78
79 public Type ProbeInNamespaces(string localName, Type[] args, int argc, bool isArray, string referenceName) {
80 foreach (var ns in m_namespases) {
81 var typeName = FormatName(new[] { ns, localName }, argc);
82
83 var resolved = Probe(typeName);
84 if (resolved != null) {
85 if (args != null && args.Length > 0) {
86 resolved = resolved.MakeGenericType(args);
87 }
88
89 if (isArray)
90 resolved = resolved.MakeArrayType();
91
92 Log("Probe succeed {0} in '{1}': {2} -> {3}", referenceName, ns, typeName, resolved.AssemblyQualifiedName);
93 return resolved;
94 } else {
95 Log("Probe failed {0} in '{1}': {2}", referenceName, ns, typeName);
96 }
97 }
98
99 return null;
100 }
101
102 Type Probe(string typeName) {
87 Type Probe(string typeName) {
103 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
88 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
104
89
105 foreach (var assembly in assemblies) {
90 foreach (var assembly in assemblies) {
106 var type = assembly.GetType(typeName);
91 var type = assembly.GetType(typeName);
107 if (type != null)
92 if (type != null)
108 return type;
93 return type;
109 }
94 }
110 return null;
95 return null;
111 }
96 }
112
113 string FormatName(string[] parts, int argc) {
114 var builder = new StringBuilder();
115
116 builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x))));
117 if (argc > 0) {
118 builder.Append('`');
119 builder.Append(argc);
120 }
121
122 return builder.ToString();
123 }
124 }
97 }
125 } No newline at end of file
98 }
@@ -1,21 +1,21
1 using System.ComponentModel;
1 using System.ComponentModel;
2 using System.Xml.Serialization;
2 using System.Xml.Serialization;
3
3
4 namespace Implab.ServiceHost.Unity {
4 namespace Implab.ServiceHost.Unity {
5 public class ValueParameterElement : InjectionParameterElement {
5 public class ValueParameterElement : InjectionParameterElement {
6 [XmlAttribute("value")]
6 [XmlAttribute("value")]
7 public string Value { get; set; }
7 public string Value { get; set; }
8
8
9 [XmlText]
9 [XmlText]
10 public string Text { get; set; }
10 public string Text { get; set; }
11
11
12 string GetTextValue() {
12 string GetTextValue() {
13 return string.IsNullOrEmpty(Value) ? Text : Value;
13 return string.IsNullOrEmpty(Value) ? Text : Value;
14 }
14 }
15
15
16 public override void Visit(InjectionValueBuilder builder) {
16 public override void Visit(InjectionParameterBuilder builder) {
17 var type = builder.ResolveInjectedValueType(TypeName);
17 var type = builder.ResolveInjectedValueType(TypeName);
18 builder.SetValue(type, TypeDescriptor.GetConverter(type).ConvertFromString(GetTextValue()));
18 builder.SetValue(type, TypeDescriptor.GetConverter(type).ConvertFromString(GetTextValue()));
19 }
19 }
20 }
20 }
21 } No newline at end of file
21 }
@@ -1,96 +1,93
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.IO;
3 using System.IO;
4 using System.Linq;
4 using System.Linq;
5 using System.Reflection;
5 using System.Reflection;
6 using System.Text;
6 using System.Text;
7 using System.Threading.Tasks;
7 using System.Threading.Tasks;
8 using System.Xml;
8 using System.Xml;
9 using System.Xml.Linq;
9 using System.Xml.Linq;
10 using System.Xml.Serialization;
10 using System.Xml.Serialization;
11
11
12 namespace Implab.Xml {
12 namespace Implab.Xml {
13 public static class SerializationHelpers {
13 public static class SerializationHelpers {
14 public static string SerializeAsString<T>(T obj) {
14 public static string SerializeAsString<T>(T obj) {
15 return SerializersPool<T>.Instance.SerializeAsString(obj);
15 return XmlDefaultSerializer<T>.Instance.SerializeAsString(obj);
16 }
16 }
17
17
18 public static void Serialize<T>(XmlWriter writer, T obj) {
18 public static void Serialize<T>(XmlWriter writer, T obj) {
19 SerializersPool<T>.Instance.Serialize(writer, obj);
19 XmlDefaultSerializer<T>.Instance.Serialize(writer, obj);
20 }
20 }
21
21
22 public static XmlDocument SerializeAsXmlDocument<T>(T obj) {
22 public static XmlDocument SerializeAsXmlDocument<T>(T obj) {
23 var doc = new XmlDocument();
23 var doc = new XmlDocument();
24 using (var writer = doc.CreateNavigator().AppendChild()) {
24 using (var writer = doc.CreateNavigator().AppendChild()) {
25 SerializersPool<T>.Instance.Serialize(writer, obj);
25 XmlDefaultSerializer<T>.Instance.Serialize(writer, obj);
26 }
26 }
27 return doc;
27 return doc;
28 }
28 }
29
29
30 public static XDocument SerializeAsXDocument<T>(T obj) {
30 public static XDocument SerializeAsXDocument<T>(T obj) {
31 var doc = new XDocument();
31 var doc = new XDocument();
32 using (var writer = doc.CreateWriter()) {
32 using (var writer = doc.CreateWriter()) {
33 SerializersPool<T>.Instance.Serialize(writer, obj);
33 XmlDefaultSerializer<T>.Instance.Serialize(writer, obj);
34 }
34 }
35 return doc;
35 return doc;
36 }
36 }
37
37
38 public static void SerializeToFile<T>(string file, T obj) {
38 public static void SerializeToFile<T>(string file, T obj) {
39 using (var writer = File.CreateText(file))
39 XmlDefaultSerializer<T>.Instance.SerializeToFile(obj, file);
40 SerializersPool<T>.Instance.Serialize(writer, obj);
41 }
40 }
42
41
43 public static void SerializeToElementChild<T>(XmlElement element, T obj) {
42 public static void SerializeToElementChild<T>(XmlElement element, T obj) {
44 using(var writer = element.CreateNavigator().AppendChild())
43 XmlDefaultSerializer<T>.Instance.Serialize(obj, element);
45 SerializersPool<T>.Instance.Serialize(writer, obj);
46 }
44 }
47
45
48 public static T Deserialize<T>(XmlReader reader) {
46 public static T Deserialize<T>(XmlReader reader) {
49 return SerializersPool<T>.Instance.Deserialize(reader);
47 return (T)XmlDefaultSerializer<T>.Instance.Deserialize(reader);
50 }
48 }
51
49
52 public static T DeserializeFromFile<T>(string file) {
50 public static T DeserializeFromFile<T>(string file) {
53 using(var reader = XmlReader.Create(File.OpenText(file)))
51 return (T)XmlDefaultSerializer<T>.Instance.DeserializeFromFile(file);
54 return Deserialize<T>(reader);
55 }
52 }
56
53
57 public static T DeserializeFromString<T>(string data) {
54 public static T DeserializeFromString<T>(string data) {
58 return SerializersPool<T>.Instance.DeserializeFromString(data);
55 return (T)XmlDefaultSerializer<T>.Instance.DeserializeFromString(data);
59 }
56 }
60
57
61 public static T DeserializeFromXmlNode<T>(XmlNode node) {
58 public static T DeserializeFromXmlNode<T>(XmlNode node) {
62 Safe.ArgumentNotNull(node, nameof(node));
59 Safe.ArgumentNotNull(node, nameof(node));
63 using (var reader = node.CreateNavigator().ReadSubtree())
60 using (var reader = node.CreateNavigator().ReadSubtree())
64 return SerializersPool<T>.Instance.Deserialize(reader);
61 return (T)XmlDefaultSerializer<T>.Instance.Deserialize(reader);
65 }
62 }
66
63
67 public static T DeserializeJson<T>(TextReader textReader) {
64 public static T DeserializeJson<T>(TextReader textReader) {
68 var options = new JsonXmlReaderOptions {
65 var options = new JsonXmlReaderOptions {
69 NamespaceUri = typeof(T).GetCustomAttribute<XmlRootAttribute>()?.Namespace,
66 NamespaceUri = typeof(T).GetCustomAttribute<XmlRootAttribute>()?.Namespace,
70 RootName = typeof(T).Name,
67 RootName = typeof(T).Name,
71 FlattenArrays = true
68 FlattenArrays = true
72 };
69 };
73
70
74 using(var reader = JsonXmlReader.CreateJsonXmlReader(textReader, options))
71 using (var reader = JsonXmlReader.CreateJsonXmlReader(textReader, options))
75 return Deserialize<T>(reader);
72 return Deserialize<T>(reader);
76 }
73 }
77
74
78 public static T DeserializeJsonFromString<T>(string data) {
75 public static T DeserializeJsonFromString<T>(string data) {
79 using(var reader = new StringReader(data)) {
76 using (var reader = new StringReader(data)) {
80 return DeserializeJson<T>(reader);
77 return DeserializeJson<T>(reader);
81 }
78 }
82 }
79 }
83
80
84 public static void SerializeJson<T>(TextWriter writer, T obj) {
81 public static void SerializeJson<T>(TextWriter writer, T obj) {
85 var doc = SerializeAsXmlDocument(obj);
82 var doc = SerializeAsXmlDocument(obj);
86 XmlToJson.Default.Transform(doc, null, writer);
83 XmlToJson.Default.Transform(doc, null, writer);
87 }
84 }
88
85
89 public static string SerializeJsonAsString<T>(T obj) {
86 public static string SerializeJsonAsString<T>(T obj) {
90 using(var writer = new StringWriter()) {
87 using (var writer = new StringWriter()) {
91 SerializeJson(writer, obj);
88 SerializeJson(writer, obj);
92 return writer.ToString();
89 return writer.ToString();
93 }
90 }
94 }
91 }
95 }
92 }
96 }
93 }
@@ -1,76 +1,77
1 using Implab.Components;
1 using Implab.Components;
2 using System;
2 using System;
3 using System.Collections.Generic;
3 using System.Collections.Generic;
4 using System.IO;
4 using System.IO;
5 using System.Linq;
5 using System.Linq;
6 using System.Text;
6 using System.Text;
7 using System.Threading.Tasks;
7 using System.Threading.Tasks;
8 using System.Xml;
8 using System.Xml;
9 using System.Xml.Serialization;
9 using System.Xml.Serialization;
10
10
11 namespace Implab.Xml {
11 namespace Implab.Xml {
12 [Obsolete("this class will be removed, use XmlDefaultSerializer")]
12 public class SerializersPool<T> : ObjectPool<XmlSerializer> {
13 public class SerializersPool<T> : ObjectPool<XmlSerializer> {
13
14
14 static readonly SerializersPool<T> _instance = new SerializersPool<T>();
15 static readonly SerializersPool<T> _instance = new SerializersPool<T>();
15
16
16 public static SerializersPool<T> Instance {
17 public static SerializersPool<T> Instance {
17 get { return _instance; }
18 get { return _instance; }
18 }
19 }
19
20
20 #region implemented abstract members of ObjectPool
21 #region implemented abstract members of ObjectPool
21 protected override XmlSerializer CreateInstance() {
22 protected override XmlSerializer CreateInstance() {
22 return new XmlSerializer(typeof(T));
23 return new XmlSerializer(typeof(T));
23 }
24 }
24 #endregion
25 #endregion
25
26
26 public T DeserializeFromString(string data) {
27 public T DeserializeFromString(string data) {
27 using (var reader = new StringReader(data)) {
28 using (var reader = new StringReader(data)) {
28 return Deserialize(reader);
29 return Deserialize(reader);
29 }
30 }
30 }
31 }
31
32
32 public T Deserialize(TextReader reader) {
33 public T Deserialize(TextReader reader) {
33 var sr = Allocate();
34 var sr = Allocate();
34 try {
35 try {
35 return (T)sr.Deserialize(reader);
36 return (T)sr.Deserialize(reader);
36 } finally {
37 } finally {
37 Release(sr);
38 Release(sr);
38 }
39 }
39 }
40 }
40
41
41 public T Deserialize(XmlReader reader) {
42 public T Deserialize(XmlReader reader) {
42 var sr = Allocate();
43 var sr = Allocate();
43 try {
44 try {
44 return (T)sr.Deserialize(reader);
45 return (T)sr.Deserialize(reader);
45 } finally {
46 } finally {
46 Release(sr);
47 Release(sr);
47 }
48 }
48 }
49 }
49
50
50 public string SerializeAsString(T data) {
51 public string SerializeAsString(T data) {
51 using (var writer = new StringWriter()) {
52 using (var writer = new StringWriter()) {
52 Serialize(writer, data);
53 Serialize(writer, data);
53 return writer.ToString();
54 return writer.ToString();
54 }
55 }
55 }
56 }
56
57
57 public void Serialize(TextWriter writer, T data) {
58 public void Serialize(TextWriter writer, T data) {
58 var sr = Allocate();
59 var sr = Allocate();
59 try {
60 try {
60 sr.Serialize(writer, data);
61 sr.Serialize(writer, data);
61 } finally {
62 } finally {
62 Release(sr);
63 Release(sr);
63 }
64 }
64 }
65 }
65
66
66 public void Serialize(XmlWriter writer, T data) {
67 public void Serialize(XmlWriter writer, T data) {
67 var sr = Allocate();
68 var sr = Allocate();
68 try {
69 try {
69 sr.Serialize(writer, data);
70 sr.Serialize(writer, data);
70 } finally {
71 } finally {
71 Release(sr);
72 Release(sr);
72 }
73 }
73 }
74 }
74
75
75 }
76 }
76 }
77 }
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now