AssemblySource.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. namespace Caliburn.Micro
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Collections.Specialized;
  6. using System.ComponentModel;
  7. using System.Linq;
  8. using System.Reflection;
  9. #if !WinRT
  10. using System.Windows;
  11. using Caliburn.Micro.Core;
  12. #else
  13. using Windows.UI.Xaml;
  14. #endif
  15. /// <summary>
  16. /// A source of assemblies that are inspectable by the framework.
  17. /// </summary>
  18. public static class AssemblySource {
  19. /// <summary>
  20. /// The singleton instance of the AssemblySource used by the framework.
  21. /// </summary>
  22. public static readonly IObservableCollection<Assembly> Instance = new BindableCollection<Assembly>();
  23. /// <summary>
  24. /// Finds a type which matches one of the elements in the sequence of names.
  25. /// </summary>
  26. public static Func<IEnumerable<string>, Type> FindTypeByNames = names => {
  27. if (names == null) {
  28. return null;
  29. }
  30. var type = names
  31. .Join(Instance.SelectMany(a => a.GetExportedTypes()), n => n, t => t.FullName, (n, t) => t)
  32. .FirstOrDefault();
  33. return type;
  34. };
  35. }
  36. /// <summary>
  37. /// A caching subsystem for <see cref="AssemblySource"/>.
  38. /// </summary>
  39. public static class AssemblySourceCache {
  40. static bool isInstalled;
  41. static readonly IDictionary<String, Type> TypeNameCache = new Dictionary<string, Type>();
  42. /// <summary>
  43. /// Extracts the types from the spezified assembly for storing in the cache.
  44. /// </summary>
  45. public static Func<Assembly, IEnumerable<Type>> ExtractTypes = assembly =>
  46. assembly.GetExportedTypes()
  47. .Where(t =>
  48. #if !CORE
  49. typeof(UIElement).IsAssignableFrom(t) ||
  50. #endif
  51. typeof(INotifyPropertyChanged).IsAssignableFrom(t));
  52. /// <summary>
  53. /// Installs the caching subsystem.
  54. /// </summary>
  55. public static void Install() {
  56. if (isInstalled) return;
  57. isInstalled = true;
  58. AssemblySource.Instance.CollectionChanged += (s, e) => {
  59. switch (e.Action) {
  60. case NotifyCollectionChangedAction.Add:
  61. e.NewItems.OfType<Assembly>()
  62. .SelectMany(a => ExtractTypes(a))
  63. .Apply(t => TypeNameCache.Add(t.FullName, t));
  64. break;
  65. case NotifyCollectionChangedAction.Remove:
  66. case NotifyCollectionChangedAction.Replace:
  67. case NotifyCollectionChangedAction.Reset:
  68. TypeNameCache.Clear();
  69. AssemblySource.Instance
  70. .SelectMany(a => ExtractTypes(a))
  71. .Apply(t => TypeNameCache.Add(t.FullName, t));
  72. break;
  73. }
  74. };
  75. AssemblySource.Instance.Refresh();
  76. AssemblySource.FindTypeByNames = names => {
  77. if (names == null) {
  78. return null;
  79. }
  80. var type = names.Select(n => TypeNameCache.GetValueOrDefault(n)).FirstOrDefault(t => t != null);
  81. return type;
  82. };
  83. }
  84. }
  85. }