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