Auto status change to "Under Review"
@@ -0,0 +1,119 | |||||
|
1 | using System; | |||
|
2 | using System.Collections.Generic; | |||
|
3 | using System.ComponentModel; | |||
|
4 | using System.Linq; | |||
|
5 | using System.Xml.Serialization; | |||
|
6 | using Implab.Xml; | |||
|
7 | using Unity.Injection; | |||
|
8 | using Unity.Registration; | |||
|
9 | ||||
|
10 | namespace Implab.ServiceHost.Unity { | |||
|
11 | class RegistrationContext { | |||
|
12 | readonly TypeResolver m_resolver; | |||
|
13 | ||||
|
14 | List<InjectionMember> m_injections = new List<InjectionMember>(); | |||
|
15 | ||||
|
16 | Type m_defaultType; | |||
|
17 | ||||
|
18 | public Type RegistrationType { | |||
|
19 | get; | |||
|
20 | private set; | |||
|
21 | } | |||
|
22 | ||||
|
23 | public Type ImplementationType { | |||
|
24 | get; | |||
|
25 | private set; | |||
|
26 | } | |||
|
27 | ||||
|
28 | public RegistrationContext(TypeResolver resolver, string typeSpec, string implSpec) { | |||
|
29 | RegistrationType = resolver.Resolve(string.IsNullOrEmpty(typeSpec) ? implSpec : typeSpec); | |||
|
30 | ||||
|
31 | ||||
|
32 | ImplementationType = string.IsNullOrEmpty(implSpec) ? RegistrationType : resolver.Resolve(implSpec); | |||
|
33 | ||||
|
34 | if (RegistrationType.IsGenericTypeDefinition) { | |||
|
35 | m_resolver = new TypeResolver(resolver); | |||
|
36 | ||||
|
37 | foreach (var p in ImplementationType.GetGenericArguments()) | |||
|
38 | m_resolver.AddMapping(p.Name, p); | |||
|
39 | } else { | |||
|
40 | m_resolver = resolver; | |||
|
41 | } | |||
|
42 | ||||
|
43 | ||||
|
44 | } | |||
|
45 | ||||
|
46 | public InjectionMember[] Injections { | |||
|
47 | get { | |||
|
48 | return m_injections.ToArray(); | |||
|
49 | } | |||
|
50 | } | |||
|
51 | ||||
|
52 | public void Visit(ConstructorInjectionElement constructorInjection) { | |||
|
53 | var parameters = constructorInjection.Parameters?.Select(x => x.Resolve(this)).ToArray(); | |||
|
54 | ||||
|
55 | var injection = parameters != null ? new InjectionConstructor(parameters) : new InjectionConstructor(); | |||
|
56 | m_injections.Add(injection); | |||
|
57 | } | |||
|
58 | ||||
|
59 | public void Visit(MethodInjectionElement methodInjection) { | |||
|
60 | var parameters = methodInjection.Parameters?.Select(x => x.Resolve(this)).ToArray(); | |||
|
61 | ||||
|
62 | var injection = parameters != null ? new InjectionMethod(methodInjection.Name, parameters) : new InjectionMethod(methodInjection.Name); | |||
|
63 | m_injections.Add(injection); | |||
|
64 | } | |||
|
65 | ||||
|
66 | public void Visit(PropertyInjectionElement propertyInjection) { | |||
|
67 | if (propertyInjection.Value == null) | |||
|
68 | throw new Exception($"A value value must be specified for the property '{propertyInjection.Name}'"); | |||
|
69 | ||||
|
70 | try { | |||
|
71 | m_defaultType = RegistrationType.GetProperty(propertyInjection.Name)?.PropertyType; | |||
|
72 | ||||
|
73 | var parameter = propertyInjection.Value.Resolve(this); | |||
|
74 | var injection = new InjectionProperty(propertyInjection.Name, parameter); | |||
|
75 | m_injections.Add(injection); | |||
|
76 | ||||
|
77 | } finally { | |||
|
78 | m_defaultType = null; | |||
|
79 | } | |||
|
80 | ||||
|
81 | } | |||
|
82 | ||||
|
83 | Type ResolveParameterType(InjectionParameterElement injectionParameter) { | |||
|
84 | if (string.IsNullOrEmpty(injectionParameter.TypeName)) { | |||
|
85 | if (m_defaultType == null) | |||
|
86 | throw new Exception($"A type must be specified for the parameter {injectionParameter}"); | |||
|
87 | return m_defaultType; | |||
|
88 | } | |||
|
89 | return m_resolver.Resolve(injectionParameter.TypeName); | |||
|
90 | } | |||
|
91 | ||||
|
92 | public object Resolve(DefaultParameterElement defaultParameter) { | |||
|
93 | var type = ResolveParameterType(defaultParameter); | |||
|
94 | ||||
|
95 | return Safe.CreateDefaultValue(type); | |||
|
96 | } | |||
|
97 | ||||
|
98 | public object Resolve(ValueParameterElement valueParameter) { | |||
|
99 | var type = ResolveParameterType(valueParameter); | |||
|
100 | ||||
|
101 | return TypeDescriptor.GetConverter(type).ConvertFromString(valueParameter.Value); | |||
|
102 | } | |||
|
103 | ||||
|
104 | public object Resolve(SerializedParameterElement serializedParameter) { | |||
|
105 | var type = ResolveParameterType(serializedParameter); | |||
|
106 | if (serializedParameter.Content == null || serializedParameter.Content.Length == 0) | |||
|
107 | return Safe.CreateDefaultValue(type); | |||
|
108 | ||||
|
109 | var serializer = new XmlSerializer(type); | |||
|
110 | using (var reader = serializedParameter.Content[0].CreateNavigator().ReadSubtree()) | |||
|
111 | return serializer.Deserialize(reader); | |||
|
112 | } | |||
|
113 | ||||
|
114 | public InjectionParameterValue Resolve(DependencyParameterElement dependencyParameter) { | |||
|
115 | var type = ResolveParameterType(dependencyParameter); | |||
|
116 | return new ResolvedParameter(type, dependencyParameter.DependencyName); | |||
|
117 | } | |||
|
118 | } | |||
|
119 | } No newline at end of file |
@@ -1,58 +1,86 | |||||
1 | using System; |
|
1 | using System; | |
2 | using System.Diagnostics; |
|
2 | using System.Diagnostics; | |
|
3 | using System.Linq; | |||
3 | using Implab.Diagnostics; |
|
4 | using Implab.Diagnostics; | |
4 | using Implab.ServiceHost.Unity; |
|
5 | using Implab.ServiceHost.Unity; | |
5 | using Implab.Xml; |
|
6 | using Implab.Xml; | |
6 | using Unity; |
|
7 | using Unity; | |
7 | using Unity.Injection; |
|
8 | using Unity.Injection; | |
|
9 | using Unity.Registration; | |||
8 |
|
10 | |||
9 | namespace Implab.Playground { |
|
11 | namespace Implab.Playground { | |
10 |
|
12 | |||
11 | public class Foo { |
|
13 | public class Foo { | |
12 |
|
14 | |||
13 | public class Bar { |
|
15 | public class Bar { | |
14 |
|
16 | |||
15 | } |
|
17 | } | |
16 |
|
18 | |||
17 | public string Name { get; set; } |
|
19 | public string Name { get; set; } | |
18 |
|
20 | |||
19 | public int IntValue { get; set; } |
|
21 | public int IntValue { get; set; } | |
20 |
|
22 | |||
21 | public string StringValue { get; set; } |
|
23 | public string StringValue { get; set; } | |
22 |
|
24 | |||
23 | } |
|
25 | } | |
24 |
|
26 | |||
25 |
public |
|
27 | public interface IContainer<T> { | |
|
28 | T Instance { get; set; } | |||
|
29 | } | |||
|
30 | ||||
|
31 | public class Container<T> : IContainer<T> { | |||
26 | public Container() { |
|
32 | public Container() { | |
27 |
|
33 | |||
28 | } |
|
34 | } | |
29 |
|
35 | |||
30 | public Container(T instance) { |
|
36 | public Container(T instance) { | |
31 | Instance = instance; |
|
37 | Instance = instance; | |
32 | } |
|
38 | } | |
33 |
|
39 | |||
34 | public T Instance { get; set; } |
|
40 | public T Instance { get; set; } | |
35 |
|
41 | |||
36 | public void SetInstance(T value) { |
|
42 | public void SetInstance(T value) { | |
37 | Instance = value; |
|
43 | Instance = value; | |
38 | } |
|
44 | } | |
39 | } |
|
45 | } | |
40 |
|
46 | |||
41 | public class Program { |
|
47 | public class Program { | |
42 |
|
48 | |||
43 | static void Main(string[] args) { |
|
49 | static void Main(string[] args) { | |
44 | var container = new UnityContainer(); |
|
50 | var container = new UnityContainer(); | |
45 |
|
51 | |||
46 | var ctx = new ConfigurationContext(container); |
|
52 | var ctx = new ConfigurationContext(container); | |
47 |
|
53 | |||
48 | var conf = SerializationHelpers.DeserializeFromFile<ContainerElement>("data/sample.xml"); |
|
54 | var conf = SerializationHelpers.DeserializeFromFile<ContainerElement>("data/sample.xml"); | |
49 |
|
55 | |||
50 | ctx.Visit(conf); |
|
56 | ctx.Visit(conf); | |
51 |
|
57 | |||
52 |
|
|
58 | DisplayContainerRegistrations(container); | |
|
59 | ||||
|
60 | var instace1 = container.Resolve<IContainer<string>>(); | |||
|
61 | var instace2 = container.Resolve<IContainer<Foo>>(); | |||
|
62 | ||||
|
63 | } | |||
53 |
|
64 | |||
|
65 | static void DisplayContainerRegistrations(IUnityContainer theContainer) { | |||
|
66 | string regName, regType, mapTo, lifetime; | |||
|
67 | Console.WriteLine("Container has {0} Registrations:", | |||
|
68 | theContainer.Registrations.Count()); | |||
|
69 | foreach (ContainerRegistration item in theContainer.Registrations) { | |||
|
70 | regType = item.RegisteredType.FullName; | |||
|
71 | mapTo = item.MappedToType.FullName; | |||
|
72 | regName = item.Name ?? "[default]"; | |||
|
73 | lifetime = item.LifetimeManager.LifetimeType.Name; | |||
|
74 | if (mapTo != regType) { | |||
|
75 | mapTo = " -> " + mapTo; | |||
|
76 | } else { | |||
|
77 | mapTo = string.Empty; | |||
|
78 | } | |||
|
79 | lifetime = lifetime.Substring(0, lifetime.Length - "LifetimeManager".Length); | |||
|
80 | Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo, regName, lifetime); | |||
|
81 | } | |||
54 | } |
|
82 | } | |
55 |
|
83 | |||
56 |
|
84 | |||
57 | } |
|
85 | } | |
58 | } |
|
86 | } |
@@ -1,38 +1,40 | |||||
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="Implab.Playground"/> |
|
4 | <namespace name="Implab.Playground"/> | |
4 |
|
5 | |||
5 | <!-- foo1 --> |
|
6 | <!-- foo1 --> | |
6 | <register name="foo1" type="Foo"> |
|
7 | <register name="foo1" type="Foo"> | |
7 | <property name="Name"> |
|
8 | <property name="Name"> | |
8 | <value>FOO!</value> |
|
9 | <value>FOO!</value> | |
9 | </property> |
|
10 | </property> | |
10 | </register> |
|
11 | </register> | |
11 |
|
12 | |||
12 | <!-- foo2 --> |
|
13 | <!-- foo2 --> | |
13 | <register name="foo2" type="Foo"> |
|
14 | <register name="foo2" type="Foo"> | |
14 | <property name="Name"> |
|
15 | <property name="Name"> | |
15 | <value>GOOD</value> |
|
16 | <value>GOOD</value> | |
16 | </property> |
|
17 | </property> | |
17 | <property name="IntValue"> |
|
18 | <property name="IntValue"> | |
18 | <value>2</value> |
|
19 | <value>2</value> | |
19 | </property> |
|
20 | </property> | |
20 | </register> |
|
21 | </register> | |
21 |
|
22 | |||
22 | <register type="Foo"> |
|
23 | <register type="Foo"> | |
23 | </register> |
|
24 | </register> | |
24 |
|
25 | |||
25 | <register type="Container{}"> |
|
26 | <register provides="IContainer{}" type="Container{}"> | |
26 | <constructor/> |
|
27 | <constructor/> | |
27 | <method name="SetInstance"> |
|
28 | <method name="SetInstance"> | |
28 | <dependency type="T"/> |
|
29 | <dependency type="T"/> | |
29 | </method> |
|
30 | </method> | |
30 | </register> |
|
31 | </register> | |
31 |
|
32 | |||
32 | <register type="Container{String}"> |
|
33 | <register provides="IContainer{String}" type="Container{String}"> | |
33 | <property name="Instance"> |
|
34 | <constructor/> | |
34 | <value>Hello!</value> |
|
35 | <method name="SetInstance"> | |
35 | </property> |
|
36 | <value type="String">Hello!</value> | |
|
37 | </method> | |||
36 | </register> |
|
38 | </register> | |
37 |
|
39 | |||
38 | </container> No newline at end of file |
|
40 | </container> |
@@ -1,7 +1,8 | |||||
|
1 | using System; | |||
|
2 | ||||
1 | namespace Implab.ServiceHost.Unity |
|
3 | namespace Implab.ServiceHost.Unity | |
2 | { |
|
4 | { | |
3 | public abstract class AbstractInjectionElement |
|
5 | public abstract class AbstractInjectionElement { | |
4 | { |
|
6 | internal abstract void Visit(RegistrationContext context); | |
5 |
|
||||
6 | } |
|
7 | } | |
7 | } No newline at end of file |
|
8 | } |
@@ -1,34 +1,32 | |||||
1 | using System; |
|
1 | using System; | |
2 | using System.Xml.Serialization; |
|
2 | using System.Xml.Serialization; | |
3 | using Unity.Lifetime; |
|
3 | using Unity.Lifetime; | |
4 | using Unity.Registration; |
|
4 | using Unity.Registration; | |
5 |
|
5 | |||
6 | namespace Implab.ServiceHost.Unity |
|
6 | namespace Implab.ServiceHost.Unity | |
7 | { |
|
7 | { | |
8 | public abstract class AbstractRegistration : IConfigurationElement { |
|
8 | public abstract class AbstractRegistration : IConfigurationElement { | |
9 |
|
9 | |||
10 | /// <summary> |
|
10 | /// <summary> | |
11 | /// An optional name for a registration in the container |
|
11 | /// An optional name for a registration in the container | |
12 | /// </summary> |
|
12 | /// </summary> | |
13 | [XmlAttribute("name")] |
|
13 | [XmlAttribute("name")] | |
14 | public string Name { |
|
14 | public string Name { | |
15 | get; set; |
|
15 | get; set; | |
16 | } |
|
16 | } | |
17 |
|
17 | |||
18 | [XmlElement("signleton", typeof(SimgletonLifetimeElement))] |
|
18 | [XmlElement("signleton", typeof(SimgletonLifetimeElement))] | |
19 | [XmlElement("context", typeof(ContextLifetimeElement))] |
|
19 | [XmlElement("context", typeof(ContextLifetimeElement))] | |
20 | [XmlElement("container", typeof(ContainerLifetimeElement))] |
|
20 | [XmlElement("container", typeof(ContainerLifetimeElement))] | |
21 | [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))] |
|
21 | [XmlElement("hierarchy", typeof(HierarchicalLifetimeElement))] | |
22 | public LifetimeElement Lifetime {get; set;} |
|
22 | public LifetimeElement Lifetime {get; set;} | |
23 |
|
23 | |||
24 | /// <summary> |
|
24 | /// <summary> | |
25 | /// A type specification for the service registration, |
|
25 | /// A type specification for the service registration, | |
26 | /// </summary> |
|
26 | /// </summary> | |
27 | [XmlAttribute("provides")] |
|
27 | [XmlAttribute("provides")] | |
28 | public string ProvidesType { get; set; } |
|
28 | public string ProvidesType { get; set; } | |
29 |
|
29 | |||
30 |
public void Visit(ConfigurationContext context) |
|
30 | public abstract void Visit(ConfigurationContext context); | |
31 | context.Visit(this); |
|
|||
32 | } |
|
|||
33 | } |
|
31 | } | |
34 | } No newline at end of file |
|
32 | } |
@@ -1,64 +1,78 | |||||
1 | using System; |
|
1 | using System; | |
2 | using System.Collections.Generic; |
|
2 | using System.Collections.Generic; | |
3 | using System.Text.RegularExpressions; |
|
3 | using System.Text.RegularExpressions; | |
4 | using Implab.Diagnostics; |
|
4 | using Implab.Diagnostics; | |
5 |
|
5 | |||
6 | namespace Implab.ServiceHost.Unity { |
|
6 | namespace Implab.ServiceHost.Unity { | |
7 | using System.Linq; |
|
7 | using System.Linq; | |
8 | using System.Reflection; |
|
8 | using System.Reflection; | |
9 | using System.Text; |
|
9 | using System.Text; | |
10 | using global::Unity; |
|
10 | using global::Unity; | |
|
11 | using global::Unity.Registration; | |||
11 | using Implab.Xml; |
|
12 | using Implab.Xml; | |
12 | using static Trace<ConfigurationContext>; |
|
13 | using static Trace<ConfigurationContext>; | |
13 |
|
14 | |||
14 | public class ConfigurationContext { |
|
15 | public class ConfigurationContext { | |
15 |
|
16 | |||
16 | readonly TypeResolver m_resolver; |
|
17 | readonly TypeResolver m_resolver; | |
17 |
|
18 | |||
18 |
|
19 | readonly UnityContainer m_container; | ||
19 |
|
20 | |||
20 | readonly UnityContainer m_container; |
|
|||
21 |
|
||||
22 | public ConfigurationContext(UnityContainer container) { |
|
21 | public ConfigurationContext(UnityContainer container) { | |
23 | m_container = container ?? new UnityContainer(); |
|
22 | m_container = container ?? new UnityContainer(); | |
24 | m_resolver = new TypeResolver(); |
|
23 | m_resolver = new TypeResolver(); | |
25 | } |
|
24 | } | |
26 |
|
25 | |||
27 |
|
26 | |||
28 | public Type Resolve(string typeReference) { |
|
27 | public Type Resolve(string typeReference) { | |
29 | return m_resolver.Resolve(TypeReference.Parse(typeReference)); |
|
28 | return m_resolver.Resolve(TypeReference.Parse(typeReference)); | |
30 | } |
|
29 | } | |
31 |
|
30 | |||
32 |
internal void Visit( |
|
31 | internal void Visit(RegisterElement descriptor) { | |
33 |
|
32 | var registrationContext = new RegistrationContext(m_resolver, descriptor.ProvidesType, descriptor.ImplementationType); | ||
|
33 | ||||
|
34 | if (descriptor.Injectors != null) { | |||
|
35 | foreach (var injector in descriptor.Injectors) { | |||
|
36 | injector.Visit(registrationContext); | |||
|
37 | } | |||
|
38 | } | |||
|
39 | ||||
|
40 | m_container.RegisterType( | |||
|
41 | registrationContext.RegistrationType, | |||
|
42 | registrationContext.ImplementationType, | |||
|
43 | descriptor.Name, | |||
|
44 | descriptor.Lifetime?.GetLifetimeManager(this), | |||
|
45 | registrationContext.Injections | |||
|
46 | ); | |||
|
47 | ||||
34 | } |
|
48 | } | |
35 |
|
49 | |||
36 | internal void Visit(NamespaceElement namespaceElement) { |
|
50 | internal void Visit(NamespaceElement namespaceElement) { | |
37 | m_resolver.AddNamespace(namespaceElement.Name); |
|
51 | m_resolver.AddNamespace(namespaceElement.Name); | |
38 | } |
|
52 | } | |
39 |
|
53 | |||
40 | internal void Visit(AssemblyElement assemblyElement) { |
|
54 | internal void Visit(AssemblyElement assemblyElement) { | |
41 | Assembly.Load(assemblyElement.AssemblyName); |
|
55 | Assembly.Load(assemblyElement.AssemblyName); | |
42 | } |
|
56 | } | |
43 |
|
57 | |||
44 | internal void Visit(IncludeElement includeElement) { |
|
58 | internal void Visit(IncludeElement includeElement) { | |
45 | Include(includeElement.Href); |
|
59 | Include(includeElement.Href); | |
46 | } |
|
60 | } | |
47 |
|
61 | |||
48 | public void Include(string file) { |
|
62 | public void Include(string file) { | |
49 | var includeContext = new ConfigurationContext(m_container); |
|
63 | var includeContext = new ConfigurationContext(m_container); | |
50 | includeContext.LoadConfig(file); |
|
64 | includeContext.LoadConfig(file); | |
51 | } |
|
65 | } | |
52 |
|
66 | |||
53 | public void LoadConfig(string file) { |
|
67 | public void LoadConfig(string file) { | |
54 | var config = SerializationHelpers.DeserializeFromFile<ContainerElement>(file); |
|
68 | var config = SerializationHelpers.DeserializeFromFile<ContainerElement>(file); | |
55 | Visit(config); |
|
69 | Visit(config); | |
56 | } |
|
70 | } | |
57 |
|
71 | |||
58 | public void Visit(ContainerElement containerElement) { |
|
72 | public void Visit(ContainerElement containerElement) { | |
59 | foreach (var item in containerElement.Items) |
|
73 | foreach (var item in containerElement.Items) | |
60 | item.Visit(this); |
|
74 | item.Visit(this); | |
61 | } |
|
75 | } | |
62 |
|
76 | |||
63 | } |
|
77 | } | |
64 | } No newline at end of file |
|
78 | } |
@@ -1,12 +1,16 | |||||
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 ConstructorInjectionElement : AbstractInjectionElement { |
|
4 | public class ConstructorInjectionElement : AbstractInjectionElement { | |
5 |
|
5 | |||
6 | [XmlElement("dependency", typeof(DependencyParameterElement))] |
|
6 | [XmlElement("dependency", typeof(DependencyParameterElement))] | |
7 | [XmlElement("value", typeof(ValueParameterElement))] |
|
7 | [XmlElement("value", typeof(ValueParameterElement))] | |
8 | [XmlElement("serialized", typeof(SerializedParameterElement))] |
|
8 | [XmlElement("serialized", typeof(SerializedParameterElement))] | |
9 | [XmlElement("default", typeof(DefaultParameterElement))] |
|
9 | [XmlElement("default", typeof(DefaultParameterElement))] | |
10 | public InjectionParameterElement[] Parameters { get; set; } |
|
10 | public InjectionParameterElement[] Parameters { get; set; } | |
|
11 | ||||
|
12 | internal override void Visit(RegistrationContext context) { | |||
|
13 | context.Visit(this); | |||
|
14 | } | |||
11 | } |
|
15 | } | |
12 | } No newline at end of file |
|
16 | } |
@@ -1,7 +1,8 | |||||
1 | namespace Implab.ServiceHost.Unity |
|
1 | namespace Implab.ServiceHost.Unity | |
2 | { |
|
2 | { | |
3 | public class DefaultParameterElement : InjectionParameterElement |
|
3 | public class DefaultParameterElement : InjectionParameterElement { | |
4 | { |
|
4 | internal override object Resolve(RegistrationContext context) { | |
5 |
|
5 | return context.Resolve(this); | ||
|
6 | } | |||
6 | } |
|
7 | } | |
7 | } No newline at end of file |
|
8 | } |
@@ -1,7 +1,16 | |||||
1 | namespace Implab.ServiceHost.Unity |
|
1 | using System.Xml.Serialization; | |
2 | { |
|
2 | ||
3 | public class DependencyParameterElement : InjectionParameterElement |
|
3 | namespace Implab.ServiceHost.Unity { | |
4 | { |
|
4 | public class DependencyParameterElement : InjectionParameterElement { | |
5 |
|
5 | |||
|
6 | [XmlAttribute("name")] | |||
|
7 | public string DependencyName { get; set; } | |||
|
8 | ||||
|
9 | [XmlAttribute("optional")] | |||
|
10 | public bool Optional { get; set; } | |||
|
11 | ||||
|
12 | internal override object Resolve(RegistrationContext context) { | |||
|
13 | return context.Resolve(this); | |||
|
14 | } | |||
6 | } |
|
15 | } | |
7 | } No newline at end of file |
|
16 | } |
@@ -1,9 +1,11 | |||||
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 InjectionParameterElement { |
|
4 | public abstract class InjectionParameterElement { | |
5 |
|
5 | |||
6 | [XmlAttribute("type")] |
|
6 | [XmlAttribute("type")] | |
7 | public string TypeName { get; set; } |
|
7 | public string TypeName { get; set; } | |
|
8 | ||||
|
9 | internal abstract object Resolve(RegistrationContext context); | |||
8 | } |
|
10 | } | |
9 | } No newline at end of file |
|
11 | } |
@@ -1,16 +1,19 | |||||
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 MethodInjectionElement : AbstractInjectionElement { |
|
4 | public class MethodInjectionElement : AbstractInjectionElement { | |
5 |
|
5 | |||
6 | [XmlAttribute("name")] |
|
6 | [XmlAttribute("name")] | |
7 | public string Name { get; set; } |
|
7 | public string Name { get; set; } | |
8 |
|
8 | |||
9 | [XmlElement("dependency", typeof(DependencyParameterElement))] |
|
9 | [XmlElement("dependency", typeof(DependencyParameterElement))] | |
10 | [XmlElement("value", typeof(ValueParameterElement))] |
|
10 | [XmlElement("value", typeof(ValueParameterElement))] | |
11 | [XmlElement("serialized", typeof(SerializedParameterElement))] |
|
11 | [XmlElement("serialized", typeof(SerializedParameterElement))] | |
12 | [XmlElement("default", typeof(DefaultParameterElement))] |
|
12 | [XmlElement("default", typeof(DefaultParameterElement))] | |
13 | public InjectionParameterElement[] Parameters { get; set; } |
|
13 | public InjectionParameterElement[] Parameters { get; set; } | |
14 |
|
14 | |||
|
15 | internal override void Visit(RegistrationContext context) { | |||
|
16 | context.Visit(this); | |||
|
17 | } | |||
15 | } |
|
18 | } | |
16 | } No newline at end of file |
|
19 | } |
@@ -1,12 +1,19 | |||||
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 PropertyInjectionElement : AbstractInjectionElement { |
|
4 | public class PropertyInjectionElement : AbstractInjectionElement { | |
5 |
|
5 | |||
|
6 | [XmlAttribute("name")] | |||
|
7 | public string Name { get; set; } | |||
|
8 | ||||
6 | [XmlElement("dependency", typeof(DependencyParameterElement))] |
|
9 | [XmlElement("dependency", typeof(DependencyParameterElement))] | |
7 | [XmlElement("value", typeof(ValueParameterElement))] |
|
10 | [XmlElement("value", typeof(ValueParameterElement))] | |
8 | [XmlElement("serialized", typeof(SerializedParameterElement))] |
|
11 | [XmlElement("serialized", typeof(SerializedParameterElement))] | |
9 | [XmlElement("default", typeof(DefaultParameterElement))] |
|
12 | [XmlElement("default", typeof(DefaultParameterElement))] | |
10 | public InjectionParameterElement Value { get; set; } |
|
13 | public InjectionParameterElement Value { get; set; } | |
|
14 | ||||
|
15 | internal override void Visit(RegistrationContext context) { | |||
|
16 | context.Visit(this); | |||
|
17 | } | |||
11 | } |
|
18 | } | |
12 | } No newline at end of file |
|
19 | } |
@@ -1,24 +1,28 | |||||
1 | using System; |
|
1 | using System; | |
2 | using System.Xml.Serialization; |
|
2 | using System.Xml.Serialization; | |
3 | using Unity.Lifetime; |
|
3 | using Unity.Lifetime; | |
4 | using Unity.Registration; |
|
4 | using Unity.Registration; | |
5 |
|
5 | |||
6 | namespace Implab.ServiceHost.Unity { |
|
6 | namespace Implab.ServiceHost.Unity { | |
7 |
|
7 | |||
8 | [XmlRoot("register", Namespace = Schema.ContainerConfigurationNamespace)] |
|
8 | [XmlRoot("register", Namespace = Schema.ContainerConfigurationNamespace)] | |
9 | public class RegisterElement : AbstractRegistration { |
|
9 | public class RegisterElement : AbstractRegistration { | |
10 |
|
10 | |||
11 | /// <summary> |
|
11 | /// <summary> | |
12 | /// An optional type which is registered as a service in the container, must be assignable to <see cref="ProvidesType">. |
|
12 | /// An optional type which is registered as a service in the container, must be assignable to <see cref="ProvidesType">. | |
13 | /// </summary> |
|
13 | /// </summary> | |
14 | [XmlAttribute("type")] |
|
14 | [XmlAttribute("type")] | |
15 |
public string Implement |
|
15 | public string ImplementationType { get; set; } | |
16 |
|
16 | |||
17 |
|
17 | |||
18 | [XmlElement("constructor", typeof(ConstructorInjectionElement))] |
|
18 | [XmlElement("constructor", typeof(ConstructorInjectionElement))] | |
19 | [XmlElement("property", typeof(PropertyInjectionElement))] |
|
19 | [XmlElement("property", typeof(PropertyInjectionElement))] | |
20 | [XmlElement("method", typeof(MethodInjectionElement))] |
|
20 | [XmlElement("method", typeof(MethodInjectionElement))] | |
21 | public AbstractInjectionElement[] Injectors { get; set; } |
|
21 | public AbstractInjectionElement[] Injectors { get; set; } | |
|
22 | ||||
|
23 | public override void Visit(ConfigurationContext context) { | |||
|
24 | context.Visit(this); | |||
|
25 | } | |||
22 | } |
|
26 | } | |
23 |
|
27 | |||
24 | } No newline at end of file |
|
28 | } |
@@ -1,12 +1,16 | |||||
1 | using System.Xml; |
|
1 | using System.Xml; | |
2 | using System.Xml.Schema; |
|
2 | using System.Xml.Schema; | |
3 | using System.Xml.Serialization; |
|
3 | using System.Xml.Serialization; | |
4 |
|
4 | |||
5 | namespace Implab.ServiceHost.Unity |
|
5 | namespace Implab.ServiceHost.Unity | |
6 | { |
|
6 | { | |
7 | public class SerializedParameterElement : InjectionParameterElement { |
|
7 | public class SerializedParameterElement : InjectionParameterElement { | |
8 |
|
8 | |||
9 | [XmlAnyElement] |
|
9 | [XmlAnyElement] | |
10 | public XmlElement[] Content { get; set; } |
|
10 | public XmlElement[] Content { get; set; } | |
|
11 | ||||
|
12 | internal override object Resolve(RegistrationContext context) { | |||
|
13 | return context.Resolve(this); | |||
|
14 | } | |||
11 | } |
|
15 | } | |
12 | } No newline at end of file |
|
16 | } |
@@ -1,124 +1,129 | |||||
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 | { |
|
9 | { | |
10 | using static Trace<TypeResolver>; |
|
10 | using static Trace<TypeResolver>; | |
11 | public class TypeResolver |
|
11 | public class TypeResolver | |
12 | { |
|
12 | { | |
13 | readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>(); |
|
13 | readonly Dictionary<string, Type> m_cache = new Dictionary<string, Type>(); | |
14 |
|
14 | |||
15 | Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled); |
|
15 | Regex _nsRx = new Regex(@"^\w+(\.\w+)*$", RegexOptions.Compiled); | |
16 | readonly LinkedList<string> m_namespases = new LinkedList<string>(); |
|
16 | readonly LinkedList<string> m_namespases = new LinkedList<string>(); | |
17 |
|
17 | |||
18 | LinkedListNode<string> m_insertAt; |
|
18 | LinkedListNode<string> m_insertAt; | |
19 |
|
19 | |||
20 | readonly TypeResolver m_parent; |
|
20 | readonly TypeResolver m_parent; | |
21 |
|
21 | |||
22 | public TypeResolver() : this(null) { |
|
22 | public TypeResolver() : this(null) { | |
23 |
|
23 | |||
24 | } |
|
24 | } | |
25 |
|
25 | |||
26 | public TypeResolver(TypeResolver parent) { |
|
26 | public TypeResolver(TypeResolver parent) { | |
|
27 | m_parent = parent; | |||
27 | m_insertAt = new LinkedListNode<string>(string.Empty); |
|
28 | m_insertAt = new LinkedListNode<string>(string.Empty); | |
28 | m_namespases.AddFirst(m_insertAt); |
|
29 | m_namespases.AddFirst(m_insertAt); | |
29 | } |
|
30 | } | |
30 |
|
31 | |||
31 | public void AddNamespace(string ns) { |
|
32 | public void AddNamespace(string ns) { | |
32 | Safe.ArgumentMatch(ns, nameof(ns), _nsRx); |
|
33 | Safe.ArgumentMatch(ns, nameof(ns), _nsRx); | |
33 | if (m_insertAt != null) |
|
34 | if (m_insertAt != null) | |
34 | m_namespases.AddAfter(m_insertAt, ns); |
|
35 | m_namespases.AddAfter(m_insertAt, ns); | |
35 | else |
|
36 | else | |
36 | m_namespases.AddFirst(ns); |
|
37 | m_namespases.AddFirst(ns); | |
37 | } |
|
38 | } | |
38 |
|
39 | |||
39 | public void AddMapping(string typeName, Type type) { |
|
40 | public void AddMapping(string typeName, Type type) { | |
40 | Safe.ArgumentNotEmpty(typeName, nameof(typeName)); |
|
41 | Safe.ArgumentNotEmpty(typeName, nameof(typeName)); | |
41 | Safe.ArgumentNotNull(type, nameof(type)); |
|
42 | Safe.ArgumentNotNull(type, nameof(type)); | |
42 |
|
43 | |||
43 | m_cache[typeName] = type; |
|
44 | m_cache[typeName] = type; | |
44 | } |
|
45 | } | |
45 |
|
46 | |||
46 | public Type Resolve(TypeReference reference) { |
|
47 | public Type Resolve(TypeReference reference) { | |
47 | var args = reference.IsGeneric && !reference.IsOpenGeneric ? reference.GenericParameters?.Select(Resolve).ToArray() : null; |
|
48 | var args = reference.IsGeneric && !reference.IsOpenGeneric ? reference.GenericParameters?.Select(Resolve).ToArray() : null; | |
48 | var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0; |
|
49 | var argc = reference.IsGeneric ? reference.GenericParameters.Length : 0; | |
49 |
|
50 | |||
50 | Type resolved; |
|
51 | Type resolved; | |
51 | if(!m_cache.TryGetValue(reference.ToString(), out resolved)) { |
|
52 | if(!m_cache.TryGetValue(reference.ToString(), out resolved)) { | |
52 | resolved = ResolveInternal(reference, args, argc); |
|
53 | resolved = ResolveInternal(reference, args, argc); | |
53 | if (resolved == null) |
|
54 | if (resolved == null) | |
54 | throw new Exception($"Failed to resolve {reference}"); |
|
55 | throw new Exception($"Failed to resolve {reference}"); | |
55 | m_cache[reference.ToString()] = resolved; |
|
56 | m_cache[reference.ToString()] = resolved; | |
56 | } |
|
57 | } | |
57 |
|
58 | |||
58 | return resolved; |
|
59 | return resolved; | |
59 | } |
|
60 | } | |
60 |
|
61 | |||
|
62 | public Type Resolve(string typeSpec) { | |||
|
63 | return Resolve(TypeReference.Parse(typeSpec)); | |||
|
64 | } | |||
|
65 | ||||
61 | Type ResolveInternal(TypeReference reference, Type[] args, int argc) { |
|
66 | Type ResolveInternal(TypeReference reference, Type[] args, int argc) { | |
62 | var resolved = ProbeInNamespaces( |
|
67 | var resolved = ProbeInNamespaces( | |
63 | String.Join(".", new [] { reference.Namespace, reference.TypeName }.Where(x => !string.IsNullOrEmpty(x)) ), |
|
68 | String.Join(".", new [] { reference.Namespace, reference.TypeName }.Where(x => !string.IsNullOrEmpty(x)) ), | |
64 | args, |
|
69 | args, | |
65 | argc, |
|
70 | argc, | |
66 | reference.IsArray, |
|
71 | reference.IsArray, | |
67 | reference.ToString() |
|
72 | reference.ToString() | |
68 | ); |
|
73 | ); | |
69 |
|
74 | |||
70 | if (resolved == null && m_parent != null) |
|
75 | if (resolved == null && m_parent != null) | |
71 | resolved = m_parent.Resolve(reference); |
|
76 | resolved = m_parent.Resolve(reference); | |
72 |
|
77 | |||
73 | return resolved; |
|
78 | return resolved; | |
74 | } |
|
79 | } | |
75 |
|
80 | |||
76 | public Type ProbeInNamespaces(string localName, Type[] args, int argc, bool isArray, string referenceName) { |
|
81 | public Type ProbeInNamespaces(string localName, Type[] args, int argc, bool isArray, string referenceName) { | |
77 | foreach (var ns in m_namespases) { |
|
82 | foreach (var ns in m_namespases) { | |
78 | var typeName = FormatName(new [] { ns, localName}, argc, args, isArray); |
|
83 | var typeName = FormatName(new [] { ns, localName}, argc, args, isArray); | |
79 |
|
84 | |||
80 | var resolved = Probe(typeName); |
|
85 | var resolved = Probe(typeName); | |
81 | if (resolved != null) { |
|
86 | if (resolved != null) { | |
82 | Log("Probe succeed {0} in '{1}': {2} -> {3}", referenceName, ns, typeName, resolved.AssemblyQualifiedName); |
|
87 | Log("Probe succeed {0} in '{1}': {2} -> {3}", referenceName, ns, typeName, resolved.AssemblyQualifiedName); | |
83 | return resolved; |
|
88 | return resolved; | |
84 | } else { |
|
89 | } else { | |
85 | Log("Probe failed {0} in '{1}': {2}", referenceName, ns, typeName); |
|
90 | Log("Probe failed {0} in '{1}': {2}", referenceName, ns, typeName); | |
86 | } |
|
91 | } | |
87 | } |
|
92 | } | |
88 |
|
93 | |||
89 | return null; |
|
94 | return null; | |
90 | } |
|
95 | } | |
91 |
|
96 | |||
92 | Type Probe(string typeName) { |
|
97 | Type Probe(string typeName) { | |
93 | var assemblies = AppDomain.CurrentDomain.GetAssemblies(); |
|
98 | var assemblies = AppDomain.CurrentDomain.GetAssemblies(); | |
94 |
|
99 | |||
95 | foreach(var assembly in assemblies) { |
|
100 | foreach(var assembly in assemblies) { | |
96 | var type = assembly.GetType(typeName); |
|
101 | var type = assembly.GetType(typeName); | |
97 | if (type != null) |
|
102 | if (type != null) | |
98 | return type; |
|
103 | return type; | |
99 | } |
|
104 | } | |
100 | return null; |
|
105 | return null; | |
101 | } |
|
106 | } | |
102 |
|
107 | |||
103 | string FormatName(string[] parts, int argc, Type[] args, bool isArray) { |
|
108 | string FormatName(string[] parts, int argc, Type[] args, bool isArray) { | |
104 | var builder = new StringBuilder(); |
|
109 | var builder = new StringBuilder(); | |
105 |
|
110 | |||
106 | builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x)))); |
|
111 | builder.Append(String.Join(".", parts.Where(x => !string.IsNullOrEmpty(x)))); | |
107 | if (argc > 0) { |
|
112 | if (argc > 0) { | |
108 | builder.Append('`'); |
|
113 | builder.Append('`'); | |
109 | builder.Append(argc); |
|
114 | builder.Append(argc); | |
110 | } |
|
115 | } | |
111 |
|
116 | |||
112 | if (args!= null && args.Length > 0) { |
|
117 | if (args!= null && args.Length > 0) { | |
113 | builder.Append('['); |
|
118 | builder.Append('['); | |
114 | builder.Append(string.Join(",", args.Select(x => $"[{x.AssemblyQualifiedName}]"))); |
|
119 | builder.Append(string.Join(",", args.Select(x => $"[{x.AssemblyQualifiedName}]"))); | |
115 | builder.Append(']'); |
|
120 | builder.Append(']'); | |
116 | } |
|
121 | } | |
117 |
|
122 | |||
118 | if(isArray) |
|
123 | if(isArray) | |
119 | builder.Append("[]"); |
|
124 | builder.Append("[]"); | |
120 |
|
125 | |||
121 | return builder.ToString(); |
|
126 | return builder.ToString(); | |
122 | } |
|
127 | } | |
123 | } |
|
128 | } | |
124 | } No newline at end of file |
|
129 | } |
@@ -1,7 +1,14 | |||||
|
1 | using System.Xml.Serialization; | |||
|
2 | ||||
1 | namespace Implab.ServiceHost.Unity |
|
3 | namespace Implab.ServiceHost.Unity | |
2 | { |
|
4 | { | |
3 | public class ValueParameterElement : InjectionParameterElement |
|
5 | public class ValueParameterElement : InjectionParameterElement | |
4 | { |
|
6 | { | |
5 |
|
7 | [XmlText] | ||
|
8 | public string Value { get; set; } | |||
|
9 | ||||
|
10 | internal override object Resolve(RegistrationContext context) { | |||
|
11 | return context.Resolve(this); | |||
|
12 | } | |||
6 | } |
|
13 | } | |
7 | } No newline at end of file |
|
14 | } |
@@ -1,182 +1,189 | |||||
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 System.Diagnostics; |
|
6 | using System.Diagnostics; | |
7 | using System.Collections; |
|
7 | using System.Collections; | |
8 | using System.Runtime.CompilerServices; |
|
8 | using System.Runtime.CompilerServices; | |
9 | using System.Threading.Tasks; |
|
9 | using System.Threading.Tasks; | |
10 | using System.Threading; |
|
10 | using System.Threading; | |
11 |
|
11 | |||
12 | #if NET_4_5 |
|
12 | #if NET_4_5 | |
13 | using System.Threading.Tasks; |
|
13 | using System.Threading.Tasks; | |
14 | #endif |
|
14 | #endif | |
15 |
|
15 | |||
16 | namespace Implab |
|
16 | namespace Implab | |
17 | { |
|
17 | { | |
18 | public static class Safe |
|
18 | public static class Safe | |
19 | { |
|
19 | { | |
20 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
20 | [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
21 | public static void ArgumentAssert(bool condition, string paramName) { |
|
21 | public static void ArgumentAssert(bool condition, string paramName) { | |
22 | if (!condition) |
|
22 | if (!condition) | |
23 | throw new ArgumentException("The parameter is invalid", paramName); |
|
23 | throw new ArgumentException("The parameter is invalid", paramName); | |
24 | } |
|
24 | } | |
25 |
|
25 | |||
26 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
26 | [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
27 | public static void ArgumentMatch(string value, string paramName, Regex rx) { |
|
27 | public static void ArgumentMatch(string value, string paramName, Regex rx) { | |
28 | if (rx == null) |
|
28 | if (rx == null) | |
29 | throw new ArgumentNullException("rx"); |
|
29 | throw new ArgumentNullException("rx"); | |
30 | if (!rx.IsMatch(value)) |
|
30 | if (!rx.IsMatch(value)) | |
31 | throw new ArgumentException(String.Format("The prameter value must match {0}", rx), paramName); |
|
31 | throw new ArgumentException(String.Format("The prameter value must match {0}", rx), paramName); | |
32 | } |
|
32 | } | |
33 |
|
33 | |||
34 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
34 | [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
35 | public static void ArgumentNotEmpty(string value, string paramName) { |
|
35 | public static void ArgumentNotEmpty(string value, string paramName) { | |
36 | if (String.IsNullOrEmpty(value)) |
|
36 | if (String.IsNullOrEmpty(value)) | |
37 | throw new ArgumentException("The parameter can't be empty", paramName); |
|
37 | throw new ArgumentException("The parameter can't be empty", paramName); | |
38 | } |
|
38 | } | |
39 |
|
39 | |||
40 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
40 | [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
41 | public static void ArgumentNotEmpty<T>(T[] value, string paramName) { |
|
41 | public static void ArgumentNotEmpty<T>(T[] value, string paramName) { | |
42 | if (value == null || value.Length == 0) |
|
42 | if (value == null || value.Length == 0) | |
43 | throw new ArgumentException("The array must be not emty", paramName); |
|
43 | throw new ArgumentException("The array must be not emty", paramName); | |
44 | } |
|
44 | } | |
45 |
|
45 | |||
46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
47 | public static void ArgumentNotNull(object value, string paramName) { |
|
47 | public static void ArgumentNotNull(object value, string paramName) { | |
48 | if (value == null) |
|
48 | if (value == null) | |
49 | throw new ArgumentNullException(paramName); |
|
49 | throw new ArgumentNullException(paramName); | |
50 | } |
|
50 | } | |
51 |
|
51 | |||
52 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
52 | [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
53 | internal static void ArgumentGreaterEqThan(int value, int min, string paramName) { |
|
53 | internal static void ArgumentGreaterEqThan(int value, int min, string paramName) { | |
54 | if (value < min) |
|
54 | if (value < min) | |
55 | throw new ArgumentOutOfRangeException(paramName); |
|
55 | throw new ArgumentOutOfRangeException(paramName); | |
56 | } |
|
56 | } | |
57 |
|
57 | |||
|
58 | public static object CreateDefaultValue(Type type) { | |||
|
59 | if (type.IsValueType) | |||
|
60 | return Activator.CreateInstance(type); | |||
|
61 | ||||
|
62 | return null; | |||
|
63 | } | |||
|
64 | ||||
58 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
65 | [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
59 | public static void ArgumentInRange(bool condition, string paramName) { |
|
66 | public static void ArgumentInRange(bool condition, string paramName) { | |
60 | if (!condition) |
|
67 | if (!condition) | |
61 | throw new ArgumentOutOfRangeException(paramName); |
|
68 | throw new ArgumentOutOfRangeException(paramName); | |
62 | } |
|
69 | } | |
63 |
|
70 | |||
64 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
71 | [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
65 | public static void ArgumentOfType(object value, Type type, string paramName) { |
|
72 | public static void ArgumentOfType(object value, Type type, string paramName) { | |
66 | if (!type.IsInstanceOfType(value)) |
|
73 | if (!type.IsInstanceOfType(value)) | |
67 | throw new ArgumentException(String.Format("The parameter must be of type {0}", type), paramName); |
|
74 | throw new ArgumentException(String.Format("The parameter must be of type {0}", type), paramName); | |
68 | } |
|
75 | } | |
69 |
|
76 | |||
70 | public static void Dispose(params IDisposable[] objects) { |
|
77 | public static void Dispose(params IDisposable[] objects) { | |
71 | foreach (var d in objects) |
|
78 | foreach (var d in objects) | |
72 | if (d != null) |
|
79 | if (d != null) | |
73 | d.Dispose(); |
|
80 | d.Dispose(); | |
74 | } |
|
81 | } | |
75 |
|
82 | |||
76 | public static void Dispose(params object[] objects) { |
|
83 | public static void Dispose(params object[] objects) { | |
77 | foreach (var obj in objects) { |
|
84 | foreach (var obj in objects) { | |
78 | var d = obj as IDisposable; |
|
85 | var d = obj as IDisposable; | |
79 | if (d != null) |
|
86 | if (d != null) | |
80 | d.Dispose(); |
|
87 | d.Dispose(); | |
81 | } |
|
88 | } | |
82 | } |
|
89 | } | |
83 |
|
90 | |||
84 | public static void DisposeCollection(IEnumerable<IDisposable> objects) { |
|
91 | public static void DisposeCollection(IEnumerable<IDisposable> objects) { | |
85 | foreach (var d in objects) |
|
92 | foreach (var d in objects) | |
86 | Dispose(d); |
|
93 | Dispose(d); | |
87 | } |
|
94 | } | |
88 |
|
95 | |||
89 | public static void DisposeCollection(IEnumerable objects) { |
|
96 | public static void DisposeCollection(IEnumerable objects) { | |
90 | foreach (var d in objects) |
|
97 | foreach (var d in objects) | |
91 | Dispose(d); |
|
98 | Dispose(d); | |
92 | } |
|
99 | } | |
93 |
|
100 | |||
94 | public static void Dispose(object obj) { |
|
101 | public static void Dispose(object obj) { | |
95 | if (obj is IDisposable) |
|
102 | if (obj is IDisposable) | |
96 | Dispose((IDisposable)obj); |
|
103 | Dispose((IDisposable)obj); | |
97 |
|
104 | |||
98 | } |
|
105 | } | |
99 |
|
106 | |||
100 | [DebuggerStepThrough] |
|
107 | [DebuggerStepThrough] | |
101 | public static void DispatchEvent<T>(this EventHandler<T> handler, object sender, T args) { |
|
108 | public static void DispatchEvent<T>(this EventHandler<T> handler, object sender, T args) { | |
102 | if (handler != null) |
|
109 | if (handler != null) | |
103 | handler(sender, args); |
|
110 | handler(sender, args); | |
104 | } |
|
111 | } | |
105 |
|
112 | |||
106 | [DebuggerStepThrough] |
|
113 | [DebuggerStepThrough] | |
107 | public static void DispatchEvent(this EventHandler handler, object sender, EventArgs args) { |
|
114 | public static void DispatchEvent(this EventHandler handler, object sender, EventArgs args) { | |
108 | if (handler != null) |
|
115 | if (handler != null) | |
109 | handler(sender, args); |
|
116 | handler(sender, args); | |
110 | } |
|
117 | } | |
111 |
|
118 | |||
112 | [DebuggerStepThrough] |
|
119 | [DebuggerStepThrough] | |
113 | public static IPromise<T> Run<T>(Func<T> action) { |
|
120 | public static IPromise<T> Run<T>(Func<T> action) { | |
114 | ArgumentNotNull(action, "action"); |
|
121 | ArgumentNotNull(action, "action"); | |
115 |
|
122 | |||
116 | try { |
|
123 | try { | |
117 | return Promise.Resolve(action()); |
|
124 | return Promise.Resolve(action()); | |
118 | } catch (Exception err) { |
|
125 | } catch (Exception err) { | |
119 | return Promise.Reject<T>(err); |
|
126 | return Promise.Reject<T>(err); | |
120 | } |
|
127 | } | |
121 | } |
|
128 | } | |
122 |
|
129 | |||
123 | [DebuggerStepThrough] |
|
130 | [DebuggerStepThrough] | |
124 | public static IPromise Run(Action action) { |
|
131 | public static IPromise Run(Action action) { | |
125 | ArgumentNotNull(action, "action"); |
|
132 | ArgumentNotNull(action, "action"); | |
126 |
|
133 | |||
127 | try { |
|
134 | try { | |
128 | action(); |
|
135 | action(); | |
129 | return Promise.Resolve(); |
|
136 | return Promise.Resolve(); | |
130 | } catch (Exception err) { |
|
137 | } catch (Exception err) { | |
131 | return Promise.Reject(err); |
|
138 | return Promise.Reject(err); | |
132 | } |
|
139 | } | |
133 | } |
|
140 | } | |
134 |
|
141 | |||
135 | [DebuggerStepThrough] |
|
142 | [DebuggerStepThrough] | |
136 | public static IPromise Run(Func<IPromise> action) { |
|
143 | public static IPromise Run(Func<IPromise> action) { | |
137 | ArgumentNotNull(action, "action"); |
|
144 | ArgumentNotNull(action, "action"); | |
138 |
|
145 | |||
139 | try { |
|
146 | try { | |
140 | return action() ?? Promise.Reject(new Exception("The action returned null")); |
|
147 | return action() ?? Promise.Reject(new Exception("The action returned null")); | |
141 | } catch (Exception err) { |
|
148 | } catch (Exception err) { | |
142 | return Promise.Reject(err); |
|
149 | return Promise.Reject(err); | |
143 | } |
|
150 | } | |
144 | } |
|
151 | } | |
145 |
|
152 | |||
146 | public static void NoWait(IPromise promise) { |
|
153 | public static void NoWait(IPromise promise) { | |
147 | } |
|
154 | } | |
148 |
|
155 | |||
149 | public static void NoWait(Task promise) { |
|
156 | public static void NoWait(Task promise) { | |
150 | } |
|
157 | } | |
151 |
|
158 | |||
152 | public static void NoWait<T>(Task<T> promise) { |
|
159 | public static void NoWait<T>(Task<T> promise) { | |
153 | } |
|
160 | } | |
154 |
|
161 | |||
155 | public static void Noop() { |
|
162 | public static void Noop() { | |
156 | } |
|
163 | } | |
157 |
|
164 | |||
158 | public static void Noop(CancellationToken ct) { |
|
165 | public static void Noop(CancellationToken ct) { | |
159 | ct.ThrowIfCancellationRequested(); |
|
166 | ct.ThrowIfCancellationRequested(); | |
160 | } |
|
167 | } | |
161 |
|
168 | |||
162 | public static Task CreateTask() { |
|
169 | public static Task CreateTask() { | |
163 | return new Task(Noop); |
|
170 | return new Task(Noop); | |
164 | } |
|
171 | } | |
165 |
|
172 | |||
166 | public static Task CreateTask(CancellationToken ct) { |
|
173 | public static Task CreateTask(CancellationToken ct) { | |
167 | return new Task(Noop, ct); |
|
174 | return new Task(Noop, ct); | |
168 | } |
|
175 | } | |
169 |
|
176 | |||
170 | [DebuggerStepThrough] |
|
177 | [DebuggerStepThrough] | |
171 | public static IPromise<T> Run<T>(Func<IPromise<T>> action) { |
|
178 | public static IPromise<T> Run<T>(Func<IPromise<T>> action) { | |
172 | ArgumentNotNull(action, "action"); |
|
179 | ArgumentNotNull(action, "action"); | |
173 |
|
180 | |||
174 | try { |
|
181 | try { | |
175 | return action() ?? Promise.Reject<T>(new Exception("The action returned null")); |
|
182 | return action() ?? Promise.Reject<T>(new Exception("The action returned null")); | |
176 | } catch (Exception err) { |
|
183 | } catch (Exception err) { | |
177 | return Promise.Reject<T>(err); |
|
184 | return Promise.Reject<T>(err); | |
178 | } |
|
185 | } | |
179 | } |
|
186 | } | |
180 |
|
187 | |||
181 | } |
|
188 | } | |
182 | } |
|
189 | } |
General Comments 3
ok, latest stable version should be in default
You need to be logged in to leave comments.
Login now