PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/MVVMSidekick/MVVMSidekick.Shared/Services.cs

https://github.com/zoujuny/MVVM-Sidekick
C# | 697 lines | 464 code | 121 blank | 112 comment | 29 complexity | 503b6ebb59a92dd02dc3a88efd05f9d7 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.ComponentModel;
  6. using System.Linq.Expressions;
  7. using System.Runtime.Serialization;
  8. using System.Reflection;
  9. using System.Threading.Tasks;
  10. using System.Threading;
  11. using System.Windows.Input;
  12. using MVVMSidekick.ViewModels;
  13. using MVVMSidekick.Commands;
  14. using System.Runtime.CompilerServices;
  15. using MVVMSidekick.Reactive;
  16. using System.Reactive.Linq;
  17. using System.Reactive.Subjects;
  18. using System.Reactive;
  19. using MVVMSidekick.EventRouting;
  20. using System.Collections.ObjectModel;
  21. using System.Collections.Specialized;
  22. using System.IO;
  23. using System.Collections;
  24. using MVVMSidekick.Utilities;
  25. #if NETFX_CORE
  26. using Windows.UI.Xaml;
  27. using Windows.UI.Xaml.Data;
  28. using Windows.UI.Xaml.Controls;
  29. using System.Collections.Concurrent;
  30. using Windows.UI.Xaml.Navigation;
  31. using Windows.UI.Xaml.Controls.Primitives;
  32. #elif WPF
  33. using System.Windows;
  34. using System.Windows.Controls;
  35. using System.Windows.Data;
  36. using System.Collections.Concurrent;
  37. using System.Windows.Navigation;
  38. using MVVMSidekick.Views;
  39. using System.Windows.Controls.Primitives;
  40. #elif SILVERLIGHT_5||SILVERLIGHT_4
  41. using System.Windows;
  42. using System.Windows.Controls;
  43. using System.Windows.Data;
  44. using System.Windows.Navigation;
  45. using System.Windows.Controls.Primitives;
  46. #elif WINDOWS_PHONE_8||WINDOWS_PHONE_7
  47. using System.Windows;
  48. using System.Windows.Controls;
  49. using Microsoft.Phone.Controls;
  50. using System.Windows.Data;
  51. using System.Windows.Navigation;
  52. using System.Windows.Controls.Primitives;
  53. #endif
  54. namespace MVVMSidekick
  55. {
  56. namespace Services
  57. {
  58. public interface IServiceLocator
  59. {
  60. bool HasInstance<TService>(string name = "");
  61. bool IsAsync<TService>(string name = "");
  62. ServiceLocatorEntryStruct<TService> Register<TService>(TService instance);
  63. ServiceLocatorEntryStruct<TService> Register<TService>(string name, TService instance);
  64. ServiceLocatorEntryStruct<TService> Register<TService>(Func<object, TService> factory, bool alwaysNew = true);
  65. ServiceLocatorEntryStruct<TService> Register<TService>(string name, Func<object, TService> factory, bool alwaysNew = true);
  66. TService Resolve<TService>(string name = null, object paremeter = null);
  67. ServiceLocatorEntryStruct<TService> Register<TService>(Func<object, Task<TService>> asyncFactory, bool alwaysNew = true);
  68. ServiceLocatorEntryStruct<TService> Register<TService>(string name, Func<object, Task<TService>> asyncFactory, bool alwaysNew = true);
  69. Task<TService> ResolveAsync<TService>(string name = null, object paremeter = null);
  70. }
  71. public interface IServiceLocator<TService>
  72. {
  73. bool HasInstance(string name = "");
  74. bool IsAsync(string name = "");
  75. ServiceLocatorEntryStruct<TService> Register(TService instance);
  76. ServiceLocatorEntryStruct<TService> Register(string name, TService instance);
  77. ServiceLocatorEntryStruct<TService> Register(Func<object, TService> factory, bool alwaysNew = true);
  78. ServiceLocatorEntryStruct<TService> Register(string name, Func<object, TService> factory, bool alwaysNew = true);
  79. TService Resolve(string name = null, object paremeter = null);
  80. ServiceLocatorEntryStruct<TService> Register(Func<object, Task<TService>> asyncFactory, bool alwaysNew = true);
  81. ServiceLocatorEntryStruct<TService> Register(string name, Func<object, Task<TService>> asyncFactory, bool alwaysNew = true);
  82. Task<TService> ResolveAsync(string name = null, object paremeter = null);
  83. }
  84. public class ServiceLocatorEntryStruct<TService>
  85. {
  86. public ServiceLocatorEntryStruct(string name)
  87. {
  88. Name = name;
  89. }
  90. public string Name { get; set; }
  91. public CacheType CacheType { get; set; }
  92. public TService ServiceInstance { private get; set; }
  93. public Func<object, TService> ServiceFactory { private get; set; }
  94. public Func<object, Task<TService>> AsyncServiceFactory { private get; set; }
  95. public bool GetIsValueCreated()
  96. {
  97. return (ServiceInstance != null && (!ServiceInstance.Equals(default(TService))));
  98. }
  99. public TService GetService(object paremeter = null)
  100. {
  101. switch (CacheType)
  102. {
  103. case CacheType.Instance:
  104. return ServiceInstance;
  105. case CacheType.Factory:
  106. return ServiceFactory(paremeter);
  107. case CacheType.LazyInstance:
  108. var rval = ServiceInstance;
  109. if (rval == null || rval.Equals(default(TService)))
  110. {
  111. lock (this)
  112. {
  113. if (ServiceInstance == null || ServiceInstance.Equals(default(TService)))
  114. {
  115. return ServiceInstance = ServiceFactory(paremeter);
  116. }
  117. }
  118. }
  119. return rval;
  120. case CacheType.AsyncFactory: // not really suguessed to acces async factory in sync method cos may lead to deadlock ,
  121. case CacheType.AsyncLazyInstance: // but still can do.
  122. Task<TService> t = GetServiceAsync(paremeter);
  123. return t.Result;
  124. default:
  125. throw new ArgumentException("No such value supported in enum " + typeof(CacheType).ToString());
  126. }
  127. }
  128. Task<TService> _NotFinishedServiceTask;
  129. public async Task<TService> GetServiceAsync(object paremeter = null)
  130. {
  131. switch (CacheType)
  132. {
  133. case CacheType.AsyncFactory:
  134. return await AsyncServiceFactory(paremeter);
  135. case CacheType.AsyncLazyInstance:
  136. if (GetIsValueCreated())
  137. {
  138. return ServiceInstance;
  139. }
  140. else
  141. {
  142. TService rval;
  143. Task<TService> rawait;
  144. lock (this)
  145. {
  146. if (GetIsValueCreated())
  147. {
  148. return ServiceInstance;
  149. }
  150. rawait = _NotFinishedServiceTask;
  151. if (rawait == null)
  152. {
  153. rawait = _NotFinishedServiceTask = AsyncServiceFactory(paremeter);
  154. }
  155. }
  156. rval = await rawait;
  157. lock (this)
  158. {
  159. ServiceInstance = rval;
  160. _NotFinishedServiceTask = null;
  161. }
  162. return rval;
  163. }
  164. default:
  165. #if SILVERLIGHT_5||WINDOWS_PHONE_7
  166. return GetService(paremeter);
  167. #else
  168. return GetService(paremeter);
  169. #endif
  170. }
  171. }
  172. }
  173. public class TypeSpecifiedServiceLocatorBase<TSubClass, TService> : IServiceLocator<TService>
  174. where TSubClass : TypeSpecifiedServiceLocatorBase<TSubClass, TService>
  175. {
  176. public ServiceLocatorEntryStruct<TService> Register(TService instance)
  177. {
  178. return Register(null, instance);
  179. }
  180. public ServiceLocatorEntryStruct<TService> Register(string name, TService instance)
  181. {
  182. name = name ?? "";
  183. return dic[name] =
  184. new ServiceLocatorEntryStruct<TService>(name)
  185. {
  186. CacheType = CacheType.Instance,
  187. ServiceInstance = instance,
  188. };
  189. }
  190. public ServiceLocatorEntryStruct<TService> Register(Func<object, TService> factory, bool alwaysNew = true)
  191. {
  192. return Register(null, factory, alwaysNew);
  193. }
  194. public ServiceLocatorEntryStruct<TService> Register(string name, Func<object, TService> factory, bool alwaysNew = true)
  195. {
  196. name = name ?? "";
  197. if (alwaysNew)
  198. {
  199. return dic[name] = new ServiceLocatorEntryStruct<TService>(name)
  200. {
  201. CacheType = CacheType.Factory,
  202. ServiceFactory = factory
  203. };
  204. }
  205. else
  206. {
  207. return dic[name] = new ServiceLocatorEntryStruct<TService>(name)
  208. {
  209. CacheType = CacheType.LazyInstance,
  210. ServiceFactory = factory
  211. };
  212. }
  213. }
  214. public TService Resolve(string name = null, object parameters = null)
  215. {
  216. name = name ?? "";
  217. var subdic = dic;
  218. ServiceLocatorEntryStruct<TService> entry = null;
  219. if (subdic.TryGetValue(name, out entry))
  220. {
  221. return entry.GetService(parameters);
  222. }
  223. else
  224. return default(TService);
  225. }
  226. static Dictionary<string, ServiceLocatorEntryStruct<TService>> dic
  227. = new Dictionary<string, ServiceLocatorEntryStruct<TService>>();
  228. public bool HasInstance(string name = "")
  229. {
  230. name = name ?? "";
  231. ServiceLocatorEntryStruct<TService> entry = null;
  232. if (dic.TryGetValue(name, out entry))
  233. {
  234. return
  235. entry.GetIsValueCreated();
  236. }
  237. else
  238. {
  239. return false;
  240. }
  241. }
  242. public ServiceLocatorEntryStruct<TService> Register(Func<object, Task<TService>> asyncFactory, bool alwaysNew = true)
  243. {
  244. return Register(null, asyncFactory, alwaysNew);
  245. }
  246. public ServiceLocatorEntryStruct<TService> Register(string name, Func<object, Task<TService>> asyncFactory, bool alwaysNew = true)
  247. {
  248. name = name ?? "";
  249. if (alwaysNew)
  250. {
  251. return dic[name] = new ServiceLocatorEntryStruct<TService>(name)
  252. {
  253. CacheType = CacheType.AsyncFactory,
  254. AsyncServiceFactory = asyncFactory
  255. };
  256. }
  257. else
  258. {
  259. return dic[name] = new ServiceLocatorEntryStruct<TService>(name)
  260. {
  261. CacheType = CacheType.AsyncLazyInstance,
  262. AsyncServiceFactory = asyncFactory
  263. };
  264. }
  265. }
  266. public async Task<TService> ResolveAsync(string name = null, object paremeter = null)
  267. {
  268. name = name ?? "";
  269. var subdic = dic;
  270. ServiceLocatorEntryStruct<TService> entry = null;
  271. if (subdic.TryGetValue(name, out entry))
  272. {
  273. return await entry.GetServiceAsync();
  274. }
  275. else
  276. //#if SILVERLIGHT_5||WINDOWS_PHONE_7
  277. // return await T.askEx.FromResult(default(TService));
  278. //#else
  279. // return await T.ask.FromResult(default(TService));
  280. //#endif
  281. return await TaskExHelper.FromResult(default(TService));
  282. }
  283. public bool IsAsync(string name = "")
  284. {
  285. name = name ?? "";
  286. ServiceLocatorEntryStruct<TService> entry = null;
  287. if (dic.TryGetValue(name, out entry))
  288. {
  289. return
  290. entry.GetIsValueCreated();
  291. }
  292. else
  293. {
  294. throw new ArgumentException("No such key");
  295. }
  296. }
  297. }
  298. public class ServiceLocatorBase<TSubClass> : IServiceLocator
  299. where TSubClass : ServiceLocatorBase<TSubClass>
  300. {
  301. Dictionary<Type, Action> disposeActions = new Dictionary<Type, Action>();
  302. public ServiceLocatorEntryStruct<TService> Register<TService>(TService instance)
  303. {
  304. return Register<TService>(null, instance);
  305. }
  306. public ServiceLocatorEntryStruct<TService> Register<TService>(string name, TService instance)
  307. {
  308. name = name ?? "";
  309. if (!disposeActions.ContainsKey(typeof(TService)))
  310. disposeActions[typeof(TService)] = () => ServiceTypedCache<TService>.dic.Clear();
  311. return ServiceTypedCache<TService>.dic[name] =
  312. new ServiceLocatorEntryStruct<TService>(name)
  313. {
  314. ServiceInstance = instance,
  315. CacheType = CacheType.Instance
  316. };
  317. }
  318. public ServiceLocatorEntryStruct<TService> Register<TService>(Func<object, TService> factory, bool alwaysNew = true)
  319. {
  320. return Register<TService>(null, factory, alwaysNew);
  321. }
  322. public ServiceLocatorEntryStruct<TService> Register<TService>(string name, Func<object, TService> factory, bool alwaysNew = true)
  323. {
  324. name = name ?? "";
  325. ServiceLocatorEntryStruct<TService> rval;
  326. if (alwaysNew)
  327. {
  328. ServiceTypedCache<TService>.dic[name] =
  329. rval =
  330. new ServiceLocatorEntryStruct<TService>(name)
  331. {
  332. ServiceFactory = factory,
  333. CacheType = CacheType.Factory
  334. };
  335. }
  336. else
  337. {
  338. ServiceTypedCache<TService>.dic[name] =
  339. rval =
  340. new ServiceLocatorEntryStruct<TService>(name)
  341. {
  342. ServiceFactory = factory,
  343. CacheType = CacheType.LazyInstance
  344. };
  345. }
  346. if (!disposeActions.ContainsKey(typeof(TService)))
  347. disposeActions[typeof(TService)] = () => ServiceTypedCache<TService>.dic.Clear();
  348. return rval;
  349. }
  350. public TService Resolve<TService>(string name = null, object paremeters = null)
  351. {
  352. name = name ?? "";
  353. var subdic = ServiceTypedCache<TService>.dic;
  354. ServiceLocatorEntryStruct<TService> entry = null;
  355. if (subdic.TryGetValue(name, out entry))
  356. {
  357. return entry.GetService(paremeters);
  358. }
  359. else
  360. return default(TService);
  361. }
  362. public void Dispose()
  363. {
  364. foreach (var act in disposeActions.Values)
  365. {
  366. try
  367. {
  368. act();
  369. }
  370. catch (Exception)
  371. {
  372. }
  373. }
  374. }
  375. static class ServiceTypedCache<TService>
  376. {
  377. public static Dictionary<string, ServiceLocatorEntryStruct<TService>> dic
  378. = new Dictionary<string, ServiceLocatorEntryStruct<TService>>();
  379. }
  380. public bool HasInstance<TService>(string name = "")
  381. {
  382. name = name ?? "";
  383. ServiceLocatorEntryStruct<TService> entry = null;
  384. if (ServiceTypedCache<TService>.dic.TryGetValue(name, out entry))
  385. {
  386. return
  387. entry.GetIsValueCreated();
  388. }
  389. else
  390. {
  391. return false;
  392. }
  393. }
  394. public bool IsAsync<TService>(string name = "")
  395. {
  396. name = name ?? "";
  397. ServiceLocatorEntryStruct<TService> entry = null;
  398. if (ServiceTypedCache<TService>.dic.TryGetValue(name, out entry))
  399. {
  400. return
  401. entry.GetIsValueCreated();
  402. }
  403. else
  404. {
  405. throw new ArgumentException("No such key");
  406. }
  407. }
  408. public ServiceLocatorEntryStruct<TService> Register<TService>(Func<object, Task<TService>> asyncFactory, bool alwaysNew = true)
  409. {
  410. return Register(null, asyncFactory, alwaysNew);
  411. }
  412. public ServiceLocatorEntryStruct<TService> Register<TService>(string name, Func<object, Task<TService>> asyncFactory, bool alwaysNew = true)
  413. {
  414. name = name ?? "";
  415. ServiceLocatorEntryStruct<TService> rval;
  416. if (alwaysNew)
  417. {
  418. ServiceTypedCache<TService>.dic[name] = rval = new ServiceLocatorEntryStruct<TService>(name)
  419. {
  420. CacheType = CacheType.AsyncFactory,
  421. AsyncServiceFactory = asyncFactory
  422. };
  423. }
  424. else
  425. {
  426. ServiceTypedCache<TService>.dic[name] = rval = new ServiceLocatorEntryStruct<TService>(name)
  427. {
  428. CacheType = CacheType.AsyncLazyInstance,
  429. AsyncServiceFactory = asyncFactory
  430. };
  431. }
  432. if (!disposeActions.ContainsKey(typeof(TService)))
  433. disposeActions[typeof(TService)] = () => ServiceTypedCache<TService>.dic.Clear();
  434. return rval;
  435. }
  436. public async Task<TService> ResolveAsync<TService>(string name = null, object paremeter = null)
  437. {
  438. name = name ?? "";
  439. var subdic = ServiceTypedCache<TService>.dic;
  440. ServiceLocatorEntryStruct<TService> entry = null;
  441. if (subdic.TryGetValue(name, out entry))
  442. {
  443. return await entry.GetServiceAsync();
  444. }
  445. else
  446. //#if SILVERLIGHT_5||WINDOWS_PHONE_7
  447. // return await T.askEx.FromResult(default(TService));
  448. //#else
  449. // return await T.ask.FromResult(default(TService));
  450. //#endif
  451. return await TaskExHelper.FromResult(default(TService));
  452. }
  453. }
  454. public enum CacheType
  455. {
  456. Instance,
  457. Factory,
  458. LazyInstance,
  459. AsyncFactory,
  460. AsyncLazyInstance
  461. }
  462. //public class DictionaryServiceLocator : IServiceLocator
  463. //{
  464. // Dictionary<Type, Dictionary<string, Tuple<Lazy<Object>, Object, Func<object, Object>, CacheType>>>
  465. // dic = new Dictionary<Type, Dictionary<string, Tuple<Lazy<Object>, Object, Func<object, Object>, CacheType>>>();
  466. // public static IServiceLocator Instance { get; set; }
  467. // public ServiceLocatorEntryStruct<TService> Register<TService>(TService instance)
  468. // {
  469. // Register<TService>(null, instance);
  470. // }
  471. // public ServiceLocatorEntryStruct<TService> Register<TService>(string name, TService instance)
  472. // {
  473. // name = name ?? "";
  474. // dic[typeof(TService)] = dic[typeof(TService)] ?? new Dictionary<string, Tuple<Lazy<Object>, Object, Func<object, Object>, CacheType>>();
  475. // dic[typeof(TService)][name] =
  476. // new Tuple<Lazy<Object>, Object, Func<object, Object>, CacheType>(
  477. // null,
  478. // instance,
  479. // null,
  480. // CacheType.Instance);
  481. // }
  482. // public ServiceLocatorEntryStruct<TService> Register<TService>(Func<object, TService> factory, bool alwaysNew = true)
  483. // {
  484. // Register<TService>(null, factory, alwaysNew);
  485. // }
  486. // public ServiceLocatorEntryStruct<TService> Register<TService>(string name, Func<object, TService> factory, bool alwaysNew = true)
  487. // {
  488. // name = name ?? "";
  489. // dic[typeof(TService)] = dic[typeof(TService)] ?? new Dictionary<string, Tuple<Lazy<Object>, Object, Func<object, Object>, CacheType>>();
  490. // if (alwaysNew)
  491. // {
  492. // dic[typeof(TService)][name] =
  493. // new Tuple<Lazy<Object>, Object, Func<object, Object>, CacheType>(
  494. // null,
  495. // default(TService),
  496. // d => factory(d) as object,
  497. // CacheType.Factory);
  498. // }
  499. // else
  500. // {
  501. // dic[typeof(TService)][name] =
  502. // new Tuple<Lazy<Object>, Object, Func<object, Object>, CacheType>(
  503. // new Lazy<object>(() => factory(null)),
  504. // default(TService),
  505. // null,
  506. // CacheType.LazyInstance);
  507. // }
  508. // }
  509. // public TService Resolve<TService>(string name = null, object parameters = null)
  510. // {
  511. // name = name ?? "";
  512. // var subdic = dic[typeof(TService)];
  513. // if (subdic != null)
  514. // {
  515. // Tuple<Lazy<Object>, Object, Func<object, Object>, CacheType> entry = null;
  516. // if (subdic.TryGetValue(name, out entry))
  517. // {
  518. // switch (entry.Item4)
  519. // {
  520. // case CacheType.Instance:
  521. // return (TService)entry.Item2;
  522. // case CacheType.Factory:
  523. // return (TService)entry.Item3(parameters);
  524. // case CacheType.LazyInstance:
  525. // return (TService)entry.Item1.Value;
  526. // default:
  527. // break;
  528. // }
  529. // return default(TService);
  530. // }
  531. // else
  532. // return default(TService);
  533. // }
  534. // else
  535. // {
  536. // return default(TService);
  537. // }
  538. // }
  539. // public void Dispose()
  540. // {
  541. // dic.Clear();
  542. // }
  543. // public bool HasInstance<TService>(string name = "")
  544. // {
  545. // name = name ?? "";
  546. // Tuple<Lazy<Object>, object, Func<object, Object>, CacheType> entry = null;
  547. // if (dic[typeof(TService)].TryGetValue(name, out entry))
  548. // {
  549. // return
  550. // (entry.Item4 == CacheType.Instance
  551. // ||
  552. // (
  553. // entry.Item4 == CacheType.LazyInstance
  554. // &&
  555. // entry.Item1.IsValueCreated)
  556. // );
  557. // }
  558. // else
  559. // {
  560. // return false;
  561. // }
  562. // }
  563. //}
  564. public sealed class ServiceLocator : ServiceLocatorBase<ServiceLocator>
  565. {
  566. static ServiceLocator()
  567. {
  568. Instance = new ServiceLocator();
  569. }
  570. private ServiceLocator()
  571. {
  572. }
  573. public static IServiceLocator Instance { get; set; }
  574. }
  575. }
  576. }