##// END OF EJS Templates
fixed unpredictable Safe.Dispose behaviour
cin -
r238:bdfdba6b645b v2
parent child
Show More
@@ -1,248 +1,248
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3
3
4 namespace Implab.Components {
4 namespace Implab.Components {
5 /// <summary>
5 /// <summary>
6 /// ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ сСрвисов, позволяСт Ρ€Π΅Π³ΠΈΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ сСрвисы.
6 /// ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ сСрвисов, позволяСт Ρ€Π΅Π³ΠΈΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ сСрвисы.
7 /// </summary>
7 /// </summary>
8 public class ServiceLocator: Disposable, IServiceLocator, IServiceProvider {
8 public class ServiceLocator: Disposable, IServiceLocator, IServiceProvider {
9 // запись ΠΎ сСрвисС
9 // запись ΠΎ сСрвисС
10 struct ServiceEntry : IDisposable {
10 class ServiceEntry : IDisposable {
11 public object service; // сСрвис
11 public object service; // сСрвис
12 public bool shared; // ΠΏΡ€ΠΈΠ·Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ сСрвис НЕ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Ρ‚ΡŒ
12 public bool shared; // ΠΏΡ€ΠΈΠ·Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ сСрвис НЕ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Ρ‚ΡŒ
13 public Func<object> activator; // Π°ΠΊΡ‚ΠΈΠ²Π°Ρ‚ΠΎΡ€ сСрвиса ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ
13 public Func<object> activator; // Π°ΠΊΡ‚ΠΈΠ²Π°Ρ‚ΠΎΡ€ сСрвиса ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ
14 public Action<object> cleanup; // функция для очистки сСрвиса
14 public Action<object> cleanup; // функция для очистки сСрвиса
15 public List<Type> associated; // ссылки Π½Π° Ρ‚Π΅ΠΊΡƒΡ‰ΡƒΡŽ запись
15 public List<Type> associated; // ссылки Π½Π° Ρ‚Π΅ΠΊΡƒΡ‰ΡƒΡŽ запись
16 public Type origin; // ссылка Π½Π° ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΡƒΡŽ запись ΠΎ сСрвисС
16 public Type origin; // ссылка Π½Π° ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΡƒΡŽ запись ΠΎ сСрвисС
17
17
18 #region IDisposable implementation
18 #region IDisposable implementation
19
19
20 public void Dispose() {
20 public void Dispose() {
21 if (shared)
21 if (shared)
22 return;
22 return;
23 if (cleanup != null) {
23 if (cleanup != null) {
24 if (service != null)
24 if (service != null)
25 cleanup(service);
25 cleanup(service);
26 } else
26 } else
27 Safe.Dispose(service);
27 Safe.Dispose(service);
28 }
28 }
29
29
30 #endregion
30 #endregion
31 }
31 }
32
32
33 // ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… сСрвисов
33 // ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… сСрвисов
34 readonly Dictionary<Type, ServiceEntry> m_services = new Dictionary<Type,ServiceEntry>();
34 readonly Dictionary<Type, ServiceEntry> m_services = new Dictionary<Type,ServiceEntry>();
35
35
36 /// <summary>
36 /// <summary>
37 /// ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис <typeparamref name="T"/>.
37 /// ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис <typeparamref name="T"/>.
38 /// </summary>
38 /// </summary>
39 /// <typeparam name="T">Π’ΠΈΠΏ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΠΎΠ³ΠΎ сСрвиса</typeparam>
39 /// <typeparam name="T">Π’ΠΈΠΏ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΠΎΠ³ΠΎ сСрвиса</typeparam>
40 /// <returns>ΠžΠ±ΡŠΠ΅ΠΊΡ‚, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ сСрвис</returns>
40 /// <returns>ΠžΠ±ΡŠΠ΅ΠΊΡ‚, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ сСрвис</returns>
41 /// <exception cref="KeyNotFoundException">БСрвис Π½Π΅ зарСгистрирован</exception>
41 /// <exception cref="KeyNotFoundException">БСрвис Π½Π΅ зарСгистрирован</exception>
42 public T GetService<T>() {
42 public T GetService<T>() {
43 object result;
43 object result;
44 if (TryGetService(typeof(T), out result))
44 if (TryGetService(typeof(T), out result))
45 return (T)result;
45 return (T)result;
46 throw new ApplicationException (String.Format ("{0} doesn't provide {1} service", this, typeof(T)));
46 throw new ApplicationException (String.Format ("{0} doesn't provide {1} service", this, typeof(T)));
47 }
47 }
48
48
49
49
50 /// <summary>
50 /// <summary>
51 /// ΠŸΡ‹Ρ‚Π°Π΅Ρ‚ΡΡ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ сСрвис, Π² случаС, Ссли ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° Π½Π΅ прСдоставляСт Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡ‹ΠΉ сСрвис
51 /// ΠŸΡ‹Ρ‚Π°Π΅Ρ‚ΡΡ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ сСрвис, Π² случаС, Ссли ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° Π½Π΅ прСдоставляСт Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡ‹ΠΉ сСрвис
52 /// Π½Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ.
52 /// Π½Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ.
53 /// </summary>
53 /// </summary>
54 /// <typeparam name="T">Π’ΠΈΠΏ Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΠΎΠ³ΠΎ сСрвиса.</typeparam>
54 /// <typeparam name="T">Π’ΠΈΠΏ Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΠΎΠ³ΠΎ сСрвиса.</typeparam>
55 /// <param name="service">ΠžΠ±ΡŠΠ΅ΠΊΡ‚ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ сСрвис, ΠΈΠ»ΠΈ <c>default(T)</c> Ссли Ρ‚Π°ΠΊΠΎΠ²ΠΎΠ³ΠΎ Π½Π΅Ρ‚.</param>
55 /// <param name="service">ΠžΠ±ΡŠΠ΅ΠΊΡ‚ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ сСрвис, ΠΈΠ»ΠΈ <c>default(T)</c> Ссли Ρ‚Π°ΠΊΠΎΠ²ΠΎΠ³ΠΎ Π½Π΅Ρ‚.</param>
56 /// <returns><c>true</c> - сСрвис Π½Π°ΠΉΠ΄Π΅Π½, <c>false</c> - сСрвис Π½Π΅ зарСгистрирован.</returns>
56 /// <returns><c>true</c> - сСрвис Π½Π°ΠΉΠ΄Π΅Π½, <c>false</c> - сСрвис Π½Π΅ зарСгистрирован.</returns>
57 public bool TryGetService<T>(out T service) {
57 public bool TryGetService<T>(out T service) {
58 object result;
58 object result;
59 if (TryGetService(typeof(T), out result)) {
59 if (TryGetService(typeof(T), out result)) {
60 service = (T)result;
60 service = (T)result;
61 return true;
61 return true;
62 }
62 }
63 service = default(T);
63 service = default(T);
64 return false;
64 return false;
65 }
65 }
66
66
67 /// <summary>
67 /// <summary>
68 /// ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис <paramref name="serviceType"/>
68 /// ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис <paramref name="serviceType"/>
69 /// </summary>
69 /// </summary>
70 /// <param name="serviceType">Π’ΠΈΠΏ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΠΎΠ³ΠΎ сСрвиса</param>
70 /// <param name="serviceType">Π’ΠΈΠΏ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΠΎΠ³ΠΎ сСрвиса</param>
71 /// <returns>ΠžΠ±ΡŠΠ΅ΠΊΡ‚, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ сСрвис</returns>
71 /// <returns>ΠžΠ±ΡŠΠ΅ΠΊΡ‚, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ сСрвис</returns>
72 /// <exception cref="KeyNotFoundException">БСрвис Π½Π΅ зарСгистрирован</exception>
72 /// <exception cref="KeyNotFoundException">БСрвис Π½Π΅ зарСгистрирован</exception>
73 public object GetService(Type serviceType) {
73 public object GetService(Type serviceType) {
74 object result;
74 object result;
75 if (TryGetService(serviceType, out result))
75 if (TryGetService(serviceType, out result))
76 return result;
76 return result;
77 throw new ApplicationException (String.Format ("{0} doesn't provide {1} service", this, serviceType));
77 throw new ApplicationException (String.Format ("{0} doesn't provide {1} service", this, serviceType));
78 }
78 }
79
79
80 /// <summary>
80 /// <summary>
81 /// ΠŸΡ‹Ρ‚Π°Π΅Ρ‚ΡΡ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡ‹ΠΉ сСрвис ΠΈΠ»ΠΈ совмСстимый с Π½ΠΈΠΌ.
81 /// ΠŸΡ‹Ρ‚Π°Π΅Ρ‚ΡΡ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡ‹ΠΉ сСрвис ΠΈΠ»ΠΈ совмСстимый с Π½ΠΈΠΌ.
82 /// </summary>
82 /// </summary>
83 /// <returns><c>true</c>, Ссли сСрвис Π±Ρ‹Π» Π½Π°ΠΉΠ΄Π΅Π½, <c>false</c> Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС..</returns>
83 /// <returns><c>true</c>, Ссли сСрвис Π±Ρ‹Π» Π½Π°ΠΉΠ΄Π΅Π½, <c>false</c> Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС..</returns>
84 /// <param name="serviceType">Π’ΠΈΠΏ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΠΎΠ³ΠΎ сСрвиса.</param>
84 /// <param name="serviceType">Π’ΠΈΠΏ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΠΎΠ³ΠΎ сСрвиса.</param>
85 /// <param name="service">Π˜ΡΠΊΠΎΠΌΡ‹ΠΉ сСрвис.</param>
85 /// <param name="service">Π˜ΡΠΊΠΎΠΌΡ‹ΠΉ сСрвис.</param>
86 public virtual bool TryGetService(Type serviceType, out object service) {
86 public virtual bool TryGetService(Type serviceType, out object service) {
87 Safe.ArgumentNotNull(serviceType, "serviceType");
87 Safe.ArgumentNotNull(serviceType, "serviceType");
88 AssertNotDisposed();
88 AssertNotDisposed();
89
89
90 ServiceEntry se;
90 ServiceEntry se;
91 if (!m_services.TryGetValue(serviceType, out se)) {
91 if (!m_services.TryGetValue(serviceType, out se)) {
92 // ΠΈΡ‰Π΅ΠΌ Π±Π»ΠΈΠΆΠ°ΠΉΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ Π½ΡƒΠΆΠ½Ρ‹ΠΉ сСрвис
92 // ΠΈΡ‰Π΅ΠΌ Π±Π»ΠΈΠΆΠ°ΠΉΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ Π½ΡƒΠΆΠ½Ρ‹ΠΉ сСрвис
93 Type pt = null;
93 Type pt = null;
94 foreach (var t in m_services.Keys)
94 foreach (var t in m_services.Keys)
95 if (serviceType.IsAssignableFrom(t) && (pt == null || t.IsAssignableFrom(pt)))
95 if (serviceType.IsAssignableFrom(t) && (pt == null || t.IsAssignableFrom(pt)))
96 pt = t;
96 pt = t;
97
97
98 if (pt == null) {
98 if (pt == null) {
99 // Π½Π΅Ρ‚ Π½ΡƒΠΆΠ½ΠΎΠ³ΠΎ сСрвиса
99 // Π½Π΅Ρ‚ Π½ΡƒΠΆΠ½ΠΎΠ³ΠΎ сСрвиса
100 service = null;
100 service = null;
101 return false;
101 return false;
102 }
102 }
103
103
104 var pe = m_services[pt];
104 var pe = m_services[pt];
105
105
106 // найдСнная запись ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡΡ‹Π»Π°Ρ‚ΡŒΡΡ Π½Π° ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΡƒΡŽ запись с сСрвисом
106 // найдСнная запись ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡΡ‹Π»Π°Ρ‚ΡŒΡΡ Π½Π° ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΡƒΡŽ запись с сСрвисом
107 if(pe.origin != null) {
107 if(pe.origin != null) {
108 pt = pe.origin;
108 pt = pe.origin;
109 pe = m_services[pt];
109 pe = m_services[pt];
110 }
110 }
111
111
112 // добавляСм список с ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹ΠΌΠΈ ссылками
112 // добавляСм список с ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹ΠΌΠΈ ссылками
113 if (pe.associated == null)
113 if (pe.associated == null)
114 pe.associated = new List<Type>();
114 pe.associated = new List<Type>();
115
115
116 pe.associated.Add(serviceType);
116 pe.associated.Add(serviceType);
117
117
118 // обновляСм Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΡƒΡŽ запись
118 // обновляСм Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΡƒΡŽ запись
119 m_services[pt] = pe;
119 m_services[pt] = pe;
120
120
121 // создаСм запись со ссылкой
121 // создаСм запись со ссылкой
122 se = new ServiceEntry {
122 se = new ServiceEntry {
123 service = pe.service,
123 service = pe.service,
124 origin = pt,
124 origin = pt,
125 shared = true // ΠΏΡ€Π΅Π΄ΠΎΡ‚Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ мноТСствСнныС ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠΈ освобоТдСния
125 shared = true // ΠΏΡ€Π΅Π΄ΠΎΡ‚Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ мноТСствСнныС ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠΈ освобоТдСния
126 };
126 };
127
127
128 m_services[serviceType] = se;
128 m_services[serviceType] = se;
129 }
129 }
130
130
131 // запись содСрТит Π² сСбС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ сСрвисС
131 // запись содСрТит Π² сСбС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ сСрвисС
132 if (se.service != null) {
132 if (se.service != null) {
133 service = se.service;
133 service = se.service;
134 return true;
134 return true;
135 }
135 }
136
136
137 // тСкущая запись являСтся ссылкой
137 // тСкущая запись являСтся ссылкой
138 if (se.origin != null) {
138 if (se.origin != null) {
139 se.service = GetService(se.origin);
139 se.service = GetService(se.origin);
140 m_services[serviceType] = se;
140 m_services[serviceType] = se;
141 service = se.service;
141 service = se.service;
142 return true;
142 return true;
143 }
143 }
144
144
145 // тСкущая запись Π½Π΅ являСтся ссылкой ΠΈ Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ сСрвисС
145 // тСкущая запись Π½Π΅ являСтся ссылкой ΠΈ Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ сСрвисС
146 // ΠΎΠ½Π° Π΄ΠΎΠ»ΠΆΠ½Π° ΡΠΎΠΆΠ΅Ρ€ΠΆΠ°Ρ‚ΡŒ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎΠ± Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ
146 // ΠΎΠ½Π° Π΄ΠΎΠ»ΠΆΠ½Π° ΡΠΎΠΆΠ΅Ρ€ΠΆΠ°Ρ‚ΡŒ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎΠ± Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ
147 if (se.activator != null) {
147 if (se.activator != null) {
148 se.service = se.activator();
148 se.service = se.activator();
149
149
150 m_services[serviceType] = se;
150 m_services[serviceType] = se;
151
151
152 service = se.service;
152 service = se.service;
153 return true;
153 return true;
154 }
154 }
155
155
156 service = null;
156 service = null;
157 return false;
157 return false;
158 }
158 }
159
159
160 /// <summary>
160 /// <summary>
161 /// РСгистрируСт Ρ„Π°Π±Ρ€ΠΈΠΊΡƒ для Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ сСрвиса ΠΏΠΎ ΠΏΠ΅Ρ€Π²ΠΎΠΌΡƒ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΡŽ.
161 /// РСгистрируСт Ρ„Π°Π±Ρ€ΠΈΠΊΡƒ для Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ сСрвиса ΠΏΠΎ ΠΏΠ΅Ρ€Π²ΠΎΠΌΡƒ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΡŽ.
162 /// </summary>
162 /// </summary>
163 /// <typeparam name="T">Π’ΠΈΠΏ рСгистрируСмого сСрвиса.</typeparam>
163 /// <typeparam name="T">Π’ΠΈΠΏ рСгистрируСмого сСрвиса.</typeparam>
164 /// <param name="activator">Π€Π°Π±Ρ€ΠΈΠΊΠ° для создания/получСния ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰Π΅Π³ΠΎ сСрвис.</param>
164 /// <param name="activator">Π€Π°Π±Ρ€ΠΈΠΊΠ° для создания/получСния ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰Π΅Π³ΠΎ сСрвис.</param>
165 /// <param name = "cleanup">ΠœΠ΅Ρ‚ΠΎΠ΄ для освобоТдСния экзСмпляра сСрвиса, Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Ρ‹Π²Π°Π½ ΠΏΡ€ΠΈ освобоТдСнии сСрвис-Π»ΠΎΠΊΠ°Ρ‚ΠΎΡ€Π°.</param>
165 /// <param name = "cleanup">ΠœΠ΅Ρ‚ΠΎΠ΄ для освобоТдСния экзСмпляра сСрвиса, Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Ρ‹Π²Π°Π½ ΠΏΡ€ΠΈ освобоТдСнии сСрвис-Π»ΠΎΠΊΠ°Ρ‚ΠΎΡ€Π°.</param>
166 /// <remarks>ΠŸΡ€ΠΈ освобоТдСнии сСрвис-Π»ΠΎΠΊΠ°Ρ‚ΠΎΡ€Π°, сСрвисы ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹Π΅ Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ освобоТдСны.</remarks>
166 /// <remarks>ΠŸΡ€ΠΈ освобоТдСнии сСрвис-Π»ΠΎΠΊΠ°Ρ‚ΠΎΡ€Π°, сСрвисы ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹Π΅ Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ освобоТдСны.</remarks>
167 public void Register<T>(Func<T> activator, Action<T> cleanup) {
167 public void Register<T>(Func<T> activator, Action<T> cleanup) {
168 Safe.ArgumentNotNull(activator, "activator");
168 Safe.ArgumentNotNull(activator, "activator");
169
169
170 AssertNotDisposed();
170 AssertNotDisposed();
171
171
172 Unregister(typeof(T));
172 Unregister(typeof(T));
173
173
174 var serviceEntry = new ServiceEntry();
174 var serviceEntry = new ServiceEntry();
175 serviceEntry.activator = () => activator();
175 serviceEntry.activator = () => activator();
176 if (cleanup != null)
176 if (cleanup != null)
177 serviceEntry.cleanup = instance => cleanup((T)instance);
177 serviceEntry.cleanup = instance => cleanup((T)instance);
178 m_services[typeof(T)] = serviceEntry;
178 m_services[typeof(T)] = serviceEntry;
179 }
179 }
180
180
181 public void Register<T>(Func<T> activator) {
181 public void Register<T>(Func<T> activator) {
182 Register(activator, null);
182 Register(activator, null);
183 }
183 }
184
184
185 /// <summary>
185 /// <summary>
186 /// РСгистрируСт ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис.
186 /// РСгистрируСт ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис.
187 /// </summary>
187 /// </summary>
188 /// <typeparam name="T">Π’ΠΈΠΏ рСгистрируСмого сСрвиса.</typeparam>
188 /// <typeparam name="T">Π’ΠΈΠΏ рСгистрируСмого сСрвиса.</typeparam>
189 /// <param name="service">ΠžΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис.</param>
189 /// <param name="service">ΠžΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис.</param>
190 /// <exception cref="InvalidOperationException">Π£ΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ сСрвис ΡƒΠΆΠ΅ зарСгистрирован.</exception>
190 /// <exception cref="InvalidOperationException">Π£ΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ сСрвис ΡƒΠΆΠ΅ зарСгистрирован.</exception>
191 /// <remarks>БСрвис-Π»ΠΎΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠΌ Π½Π΅ управляСт Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ ΠΆΠΈΠ·Π½ΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° для зарСгистрированного сСрвиса.</remarks>
191 /// <remarks>БСрвис-Π»ΠΎΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠΌ Π½Π΅ управляСт Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ ΠΆΠΈΠ·Π½ΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° для зарСгистрированного сСрвиса.</remarks>
192 public void Register<T>(T service) {
192 public void Register<T>(T service) {
193 Register(service, true);
193 Register(service, true);
194 }
194 }
195
195
196 /// <summary>
196 /// <summary>
197 /// РСгистрируСт ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис. ΠŸΠΎΠ²Ρ‚ΠΎΡ€Π½Π°Ρ рСгистрация отмСняСт ΡƒΠΆΠ΅ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ.
197 /// РСгистрируСт ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис. ΠŸΠΎΠ²Ρ‚ΠΎΡ€Π½Π°Ρ рСгистрация отмСняСт ΡƒΠΆΠ΅ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ.
198 /// </summary>
198 /// </summary>
199 /// <typeparam name="T">Π’ΠΈΠΏ рСгистрируСмого сСрвиса.</typeparam>
199 /// <typeparam name="T">Π’ΠΈΠΏ рСгистрируСмого сСрвиса.</typeparam>
200 /// <param name="service">ΠžΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис.</param>
200 /// <param name="service">ΠžΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис.</param>
201 /// <param name="shared">ΠŸΡ€ΠΈΠ·Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ являСтся раздСляСмым ΠΈ сСрвис-Π»ΠΎΠΊΠ°Ρ‚ΠΎΡ€ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π΅Π³ΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Ρ‚ΡŒ.</param>
201 /// <param name="shared">ΠŸΡ€ΠΈΠ·Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ являСтся раздСляСмым ΠΈ сСрвис-Π»ΠΎΠΊΠ°Ρ‚ΠΎΡ€ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π΅Π³ΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Ρ‚ΡŒ.</param>
202 public void Register<T>(T service, bool shared) {
202 public void Register<T>(T service, bool shared) {
203 Safe.ArgumentNotNull(service, "service");
203 Safe.ArgumentNotNull(service, "service");
204
204
205 AssertNotDisposed();
205 AssertNotDisposed();
206
206
207 Unregister(typeof(T));
207 Unregister(typeof(T));
208
208
209 m_services[typeof(T)] = new ServiceEntry { service = service, shared = shared };
209 m_services[typeof(T)] = new ServiceEntry { service = service, shared = shared };
210 }
210 }
211
211
212 public void Unregister(Type serviceType) {
212 public void Unregister(Type serviceType) {
213 Safe.ArgumentNotNull(serviceType, "serviceType");
213 Safe.ArgumentNotNull(serviceType, "serviceType");
214
214
215 AssertNotDisposed();
215 AssertNotDisposed();
216
216
217 ServiceEntry se;
217 ServiceEntry se;
218 if (m_services.TryGetValue(serviceType, out se)) {
218 if (m_services.TryGetValue(serviceType, out se)) {
219 if (se.origin != null) {
219 if (se.origin != null) {
220 var pe = m_services[se.origin];
220 var pe = m_services[se.origin];
221 pe.associated.Remove(serviceType);
221 pe.associated.Remove(serviceType);
222 }
222 }
223 // освобоТдаСм рСсурсы
223 // освобоТдаСм рСсурсы
224 se.Dispose();
224 se.Dispose();
225 m_services.Remove(serviceType);
225 m_services.Remove(serviceType);
226
226
227 // ΡƒΠ±ΠΈΡ€Π°Π΅ΠΌ связанныС записи
227 // ΡƒΠ±ΠΈΡ€Π°Π΅ΠΌ связанныС записи
228 if (se.associated != null)
228 if (se.associated != null)
229 foreach (var item in se.associated)
229 foreach (var item in se.associated)
230 m_services.Remove(item);
230 m_services.Remove(item);
231 }
231 }
232 }
232 }
233
233
234 /// <summary>
234 /// <summary>
235 /// ΠžΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅Ρ‚ зарСгистрированныС сСрвисы (ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ трСбуСтся ΠΎΡΠ²ΠΎΠ±ΠΎΠΈΡ‚ΡŒ).
235 /// ΠžΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅Ρ‚ зарСгистрированныС сСрвисы (ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ трСбуСтся ΠΎΡΠ²ΠΎΠ±ΠΎΠΈΡ‚ΡŒ).
236 /// </summary>
236 /// </summary>
237 /// <param name="disposing">ΠŸΡ€ΠΈΠ·Π°Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠ΄ΠΈΡ‚ΡŒ рСсурсы.</param>
237 /// <param name="disposing">ΠŸΡ€ΠΈΠ·Π°Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠ΄ΠΈΡ‚ΡŒ рСсурсы.</param>
238 protected override void Dispose(bool disposing) {
238 protected override void Dispose(bool disposing) {
239 if (disposing) {
239 if (disposing) {
240
240
241 foreach (var entry in m_services.Values)
241 foreach (var entry in m_services.Values)
242 entry.Dispose();
242 entry.Dispose();
243
243
244 }
244 }
245 base.Dispose(disposing);
245 base.Dispose(disposing);
246 }
246 }
247 }
247 }
248 } No newline at end of file
248 }
@@ -1,166 +1,164
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
9
10 #if NET_4_5
10 #if NET_4_5
11 using System.Threading.Tasks;
11 using System.Threading.Tasks;
12 #endif
12 #endif
13
13
14 namespace Implab
14 namespace Implab
15 {
15 {
16 public static class Safe
16 public static class Safe
17 {
17 {
18 [MethodImpl(MethodImplOptions.AggressiveInlining)]
18 [MethodImpl(MethodImplOptions.AggressiveInlining)]
19 public static void ArgumentAssert(bool condition, string paramName) {
19 public static void ArgumentAssert(bool condition, string paramName) {
20 if (!condition)
20 if (!condition)
21 throw new ArgumentException("The parameter is invalid", paramName);
21 throw new ArgumentException("The parameter is invalid", paramName);
22 }
22 }
23
23
24 [MethodImpl(MethodImplOptions.AggressiveInlining)]
24 [MethodImpl(MethodImplOptions.AggressiveInlining)]
25 public static void ArgumentMatch(string value, string paramName, Regex rx) {
25 public static void ArgumentMatch(string value, string paramName, Regex rx) {
26 if (rx == null)
26 if (rx == null)
27 throw new ArgumentNullException("rx");
27 throw new ArgumentNullException("rx");
28 if (!rx.IsMatch(value))
28 if (!rx.IsMatch(value))
29 throw new ArgumentException(String.Format("The prameter value must match {0}", rx), paramName);
29 throw new ArgumentException(String.Format("The prameter value must match {0}", rx), paramName);
30 }
30 }
31
31
32 [MethodImpl(MethodImplOptions.AggressiveInlining)]
32 [MethodImpl(MethodImplOptions.AggressiveInlining)]
33 public static void ArgumentNotEmpty(string value, string paramName) {
33 public static void ArgumentNotEmpty(string value, string paramName) {
34 if (String.IsNullOrEmpty(value))
34 if (String.IsNullOrEmpty(value))
35 throw new ArgumentException("The parameter can't be empty", paramName);
35 throw new ArgumentException("The parameter can't be empty", paramName);
36 }
36 }
37
37
38 [MethodImpl(MethodImplOptions.AggressiveInlining)]
38 [MethodImpl(MethodImplOptions.AggressiveInlining)]
39 public static void ArgumentNotEmpty<T>(T[] value, string paramName) {
39 public static void ArgumentNotEmpty<T>(T[] value, string paramName) {
40 if (value == null || value.Length == 0)
40 if (value == null || value.Length == 0)
41 throw new ArgumentException("The array must be not emty", paramName);
41 throw new ArgumentException("The array must be not emty", paramName);
42 }
42 }
43
43
44 [MethodImpl(MethodImplOptions.AggressiveInlining)]
44 [MethodImpl(MethodImplOptions.AggressiveInlining)]
45 public static void ArgumentNotNull(object value, string paramName) {
45 public static void ArgumentNotNull(object value, string paramName) {
46 if (value == null)
46 if (value == null)
47 throw new ArgumentNullException(paramName);
47 throw new ArgumentNullException(paramName);
48 }
48 }
49
49
50 [MethodImpl(MethodImplOptions.AggressiveInlining)]
50 [MethodImpl(MethodImplOptions.AggressiveInlining)]
51 internal static void ArgumentGreaterThan(int value, int min, string paramName) {
51 internal static void ArgumentGreaterThan(int value, int min, string paramName) {
52 if (value < min)
52 if (value < min)
53 throw new ArgumentOutOfRangeException(paramName);
53 throw new ArgumentOutOfRangeException(paramName);
54 }
54 }
55
55
56 [MethodImpl(MethodImplOptions.AggressiveInlining)]
56 [MethodImpl(MethodImplOptions.AggressiveInlining)]
57 public static void ArgumentInRange(int value, int min, int max, string paramName) {
57 public static void ArgumentInRange(int value, int min, int max, string paramName) {
58 if (value < min || value > max)
58 if (value < min || value > max)
59 throw new ArgumentOutOfRangeException(paramName);
59 throw new ArgumentOutOfRangeException(paramName);
60 }
60 }
61
61
62 [MethodImpl(MethodImplOptions.AggressiveInlining)]
62 [MethodImpl(MethodImplOptions.AggressiveInlining)]
63 public static void ArgumentOfType(object value, Type type, string paramName) {
63 public static void ArgumentOfType(object value, Type type, string paramName) {
64 if (!type.IsInstanceOfType(value))
64 if (!type.IsInstanceOfType(value))
65 throw new ArgumentException(String.Format("The parameter must be of type {0}", type), paramName);
65 throw new ArgumentException(String.Format("The parameter must be of type {0}", type), paramName);
66 }
66 }
67
67
68 public static void Dispose(params IDisposable[] objects) {
68 public static void Dispose(params IDisposable[] objects) {
69 foreach (var d in objects)
69 foreach (var d in objects)
70 if (d != null)
70 if (d != null)
71 d.Dispose();
71 d.Dispose();
72 }
72 }
73
73
74 public static void Dispose(params object[] objects) {
74 public static void Dispose(params object[] objects) {
75 foreach (var obj in objects) {
75 foreach (var obj in objects) {
76 var d = obj as IDisposable;
76 var d = obj as IDisposable;
77 if (d != null)
77 if (d != null)
78 d.Dispose();
78 d.Dispose();
79 }
79 }
80 }
80 }
81
81
82 public static void DisposeCollection(IEnumerable<IDisposable> objects) {
82 public static void DisposeCollection(IEnumerable<IDisposable> objects) {
83 foreach (var d in objects)
83 foreach (var d in objects)
84 Dispose(d);
84 Dispose(d);
85 }
85 }
86
86
87 public static void DisposeCollection(IEnumerable objects) {
87 public static void DisposeCollection(IEnumerable objects) {
88 foreach (var d in objects)
88 foreach (var d in objects)
89 Dispose(d);
89 Dispose(d);
90 }
90 }
91
91
92 public static void Dispose(object obj) {
92 public static void Dispose(object obj) {
93 if (obj is IDisposable) {
93 if (obj is IDisposable)
94 Dispose((IDisposable)obj);
94 Dispose((IDisposable)obj);
95 } else if (obj is IEnumerable) {
95
96 DisposeCollection((IEnumerable)obj);
97 }
98 }
96 }
99
97
100 [DebuggerStepThrough]
98 [DebuggerStepThrough]
101 public static void DispatchEvent<T>(this EventHandler<T> handler, object sender, T args) {
99 public static void DispatchEvent<T>(this EventHandler<T> handler, object sender, T args) {
102 if (handler != null)
100 if (handler != null)
103 handler(sender, args);
101 handler(sender, args);
104 }
102 }
105
103
106 [DebuggerStepThrough]
104 [DebuggerStepThrough]
107 public static void DispatchEvent(this EventHandler handler, object sender, EventArgs args) {
105 public static void DispatchEvent(this EventHandler handler, object sender, EventArgs args) {
108 if (handler != null)
106 if (handler != null)
109 handler(sender, args);
107 handler(sender, args);
110 }
108 }
111
109
112 [DebuggerStepThrough]
110 [DebuggerStepThrough]
113 public static IPromise<T> Run<T>(Func<T> action) {
111 public static IPromise<T> Run<T>(Func<T> action) {
114 ArgumentNotNull(action, "action");
112 ArgumentNotNull(action, "action");
115
113
116 try {
114 try {
117 return Promise<T>.FromResult(action());
115 return Promise<T>.FromResult(action());
118 } catch (Exception err) {
116 } catch (Exception err) {
119 return Promise<T>.FromException(err);
117 return Promise<T>.FromException(err);
120 }
118 }
121 }
119 }
122
120
123 [DebuggerStepThrough]
121 [DebuggerStepThrough]
124 public static IPromise Run(Action action) {
122 public static IPromise Run(Action action) {
125 ArgumentNotNull(action, "action");
123 ArgumentNotNull(action, "action");
126
124
127 try {
125 try {
128 action();
126 action();
129 return Promise.Success;
127 return Promise.Success;
130 } catch (Exception err) {
128 } catch (Exception err) {
131 return new FailedPromise(err);
129 return new FailedPromise(err);
132 }
130 }
133 }
131 }
134
132
135 [DebuggerStepThrough]
133 [DebuggerStepThrough]
136 public static IPromise Run(Func<IPromise> action) {
134 public static IPromise Run(Func<IPromise> action) {
137 ArgumentNotNull(action, "action");
135 ArgumentNotNull(action, "action");
138
136
139 try {
137 try {
140 return action() ?? new FailedPromise(new Exception("The action returned null"));
138 return action() ?? new FailedPromise(new Exception("The action returned null"));
141 } catch (Exception err) {
139 } catch (Exception err) {
142 return new FailedPromise(err);
140 return new FailedPromise(err);
143 }
141 }
144 }
142 }
145
143
146 public static void NoWait(IPromise promise) {
144 public static void NoWait(IPromise promise) {
147 }
145 }
148
146
149 [DebuggerStepThrough]
147 [DebuggerStepThrough]
150 public static IPromise<T> Run<T>(Func<IPromise<T>> action) {
148 public static IPromise<T> Run<T>(Func<IPromise<T>> action) {
151 ArgumentNotNull(action, "action");
149 ArgumentNotNull(action, "action");
152
150
153 try {
151 try {
154 return action() ?? Promise<T>.FromException(new Exception("The action returned null"));
152 return action() ?? Promise<T>.FromException(new Exception("The action returned null"));
155 } catch (Exception err) {
153 } catch (Exception err) {
156 return Promise<T>.FromException(err);
154 return Promise<T>.FromException(err);
157 }
155 }
158 }
156 }
159
157
160 #if NET_4_5
158 #if NET_4_5
161 public static void NoWait(Task t) {
159 public static void NoWait(Task t) {
162 }
160 }
163 #endif
161 #endif
164
162
165 }
163 }
166 }
164 }
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