PluginsLoader.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics.CodeAnalysis;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Reflection;
  7. using System.Runtime.InteropServices;
  8. using System.Runtime.Loader;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. namespace IModel.Tools
  12. {
  13. public class PluginsLoader
  14. {
  15. private string _Path = "";
  16. private List<Assembly> LoadedAssemblies = new List<Assembly>();
  17. [AllowNull]
  18. private AssemblyDependencyResolver resolver;
  19. private List<string> AllDlls = new List<string>();
  20. private PluginsLoader()
  21. {
  22. }
  23. public List<T> Load<T>(string path)
  24. {
  25. try
  26. {
  27. _Path = path;
  28. resolver = new AssemblyDependencyResolver(path);
  29. AssemblyLoadContext.Default.Resolving += Default_Resolving;
  30. AssemblyLoadContext.Default.ResolvingUnmanagedDll += Default_ResolvingUnmanagedDll;
  31. AllDlls.Clear();
  32. AllDlls.AddRange(System.IO.Directory.GetFiles(path, "*.dll", System.IO.SearchOption.AllDirectories));
  33. var result = AllDlls
  34. .SelectMany(x =>
  35. {
  36. try
  37. {
  38. var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(x);
  39. var types = assembly.GetTypes();
  40. return types.Where(x => x.GetInterface(typeof(T).FullName!) != null && x.IsAnsiClass && !x.IsAbstract);
  41. }
  42. catch
  43. {
  44. }
  45. return new Type[0];
  46. })
  47. .Where(x => x != null)
  48. .Select(x =>
  49. {
  50. return (T)Activator.CreateInstance(x!)!;
  51. })
  52. .Where(x => x != null)
  53. .ToList();
  54. //AssemblyLoadContext.Default.Resolving -= Default_Resolving;
  55. return result;
  56. }
  57. catch
  58. {
  59. return new List<T>();
  60. }
  61. }
  62. [DllImport("kernel32.dll")]
  63. private extern static nint LoadLibrary(string path);
  64. private nint Default_ResolvingUnmanagedDll(Assembly arg1, string arg2)
  65. {
  66. var fileinfo = new FileInfo(arg1.Location);
  67. if (fileinfo?.Directory == null) return 0;
  68. var file = fileinfo.Directory.GetFiles(arg2, SearchOption.AllDirectories).FirstOrDefault()?.FullName;
  69. if(System.IO.File.Exists(file))
  70. {
  71. return LoadLibrary(file);
  72. }
  73. throw new NotImplementedException();
  74. }
  75. private System.Reflection.Assembly? Default_Resolving(AssemblyLoadContext arg1, System.Reflection.AssemblyName arg2)
  76. {
  77. var assembly = AssemblyLoadContext.Default.Assemblies.FirstOrDefault(x => x.FullName == arg2.FullName);
  78. if (assembly != null) return assembly;
  79. assembly = LoadedAssemblies.FirstOrDefault(x => x.FullName == arg2.FullName);
  80. if (assembly != null) return assembly;
  81. string? path = resolver.ResolveAssemblyToPath(arg2);
  82. if(!string.IsNullOrEmpty(path))
  83. {
  84. assembly = arg1.LoadFromAssemblyPath(path);
  85. if(assembly!=null)
  86. {
  87. LoadedAssemblies.Add(assembly);
  88. return assembly;
  89. }
  90. }
  91. else
  92. {
  93. var results = AllDlls.Where(x => x.IndexOf(arg2.Name!) >= 0).ToList();
  94. results.ForEach(x =>
  95. {
  96. try
  97. {
  98. var tempassembly = arg1.LoadFromAssemblyPath(x);
  99. if (tempassembly != null)
  100. {
  101. LoadedAssemblies.Add(tempassembly);
  102. }
  103. }
  104. catch
  105. {
  106. }
  107. });
  108. assembly = LoadedAssemblies.FirstOrDefault(x => x.FullName == arg2.FullName);
  109. if (assembly != null) return assembly;
  110. }
  111. return null;
  112. }
  113. static PluginsLoader()
  114. {
  115. }
  116. public static PluginsLoader Defalut { get; } = new PluginsLoader();
  117. }
  118. }