Guest User

Untitled

a guest
Jul 23rd, 2020
29
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.08 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Reflection;
  6. using System.Runtime.Loader;
  7. using System.Text.RegularExpressions;
  8.  
  9. namespace MarkHub.Core.Infrastructure
  10. {
  11. /// <summary>
  12. /// A class that finds types needed by Grand by looping assemblies in the
  13. /// currently executing AppDomain. Only assemblies whose names matches
  14. /// certain patterns are investigated and an optional list of assemblies
  15. /// referenced by <see cref="AssemblyNames"/> are always investigated.
  16. /// </summary>
  17. public class AppDomainTypeFinder : ITypeFinder
  18. {
  19. #region Fields
  20.  
  21. private bool loadAppDomainAssemblies = true;
  22. private string assemblySkipLoadingPattern = "^System|^mscorlib|^Microsoft|^Autofac|^AutoMapper|^Castle|^ComponentArt|^CppCodeProvider|^DotNetOpenAuth|^EPPlus|^FluentValidation|^ImageProcessor|^itextsharp|^log4net|^MaxMind|^MbUnit|^MiniProfiler|^Mono.Math|^MongoDB|^MvcContrib|^Newtonsoft|^NHibernate|^nunit|^Org.Mentalis|^PerlRegex|^QuickGraph|^Recaptcha|^Remotion|^RestSharp|^Iesi|^TestDriven|^TestFu|^UserAgentStringLibrary|^VJSharpCodeProvider|^WebDev|^WebGrease|^dotliquid|^fluentscheduler|^netstandard|^Google.Apis|^AWSSDK|^Braintree|^MediatR|^WebMarkupMin|^HealthChecks|^WebEssentials|^NWebsec|^NetEscapades|^Wangkanai|^dotnet-bundle|^MailKit|^MimeKit|^NUglify|^Pipelines.Sockets.Unofficial|^SharpCompress|^SkiaSharp|^StackExchange.Redis|^DnsClient|^BouncyCastle.Crypto|^AdvancedStringBuilder";
  23. private string assemblyRestrictToLoadingPattern = ".*";
  24. private IList<string> assemblyNames = new List<string>();
  25.  
  26. #endregion
  27.  
  28. #region Properties
  29.  
  30. /// <summary>Gets or sets wether Nop should iterate assemblies in the app domain when loading Nop types. Loading patterns are applied when loading these assemblies.</summary>
  31. public bool LoadAppDomainAssemblies
  32. {
  33. get { return loadAppDomainAssemblies; }
  34. set { loadAppDomainAssemblies = value; }
  35. }
  36.  
  37. /// <summary>Gets or sets assemblies loaded a startup in addition to those loaded in the AppDomain.</summary>
  38. public IList<string> AssemblyNames
  39. {
  40. get { return assemblyNames; }
  41. set { assemblyNames = value; }
  42. }
  43.  
  44. /// <summary>Gets the pattern for dlls that we know don't need to be investigated.</summary>
  45. public string AssemblySkipLoadingPattern
  46. {
  47. get { return assemblySkipLoadingPattern; }
  48. set { assemblySkipLoadingPattern = value; }
  49. }
  50.  
  51. /// <summary>Gets or sets the pattern for dll that will be investigated. For ease of use this defaults to match all but to increase performance you might want to configure a pattern that includes assemblies and your own.</summary>
  52. /// <remarks>If you change this so that Nop assemblies arn't investigated (e.g. by not including something like "^Nop|..." you may break core functionality.</remarks>
  53. public string AssemblyRestrictToLoadingPattern
  54. {
  55. get { return assemblyRestrictToLoadingPattern; }
  56. set { assemblyRestrictToLoadingPattern = value; }
  57. }
  58.  
  59. #endregion
  60.  
  61. #region Methods
  62.  
  63. public IEnumerable<Type> FindClassesOfType<T>(bool onlyConcreteClasses = true)
  64. {
  65. return FindClassesOfType(typeof(T), onlyConcreteClasses);
  66. }
  67.  
  68. public IEnumerable<Type> FindClassesOfType(Type assignTypeFrom, bool onlyConcreteClasses = true)
  69. {
  70. return FindClassesOfType(assignTypeFrom, GetAssemblies(), onlyConcreteClasses);
  71. }
  72.  
  73. public IEnumerable<Type> FindClassesOfType<T>(IEnumerable<Assembly> assemblies, bool onlyConcreteClasses = true)
  74. {
  75. return FindClassesOfType(typeof (T), assemblies, onlyConcreteClasses);
  76. }
  77.  
  78. public IEnumerable<Type> FindClassesOfType(Type assignTypeFrom, IEnumerable<Assembly> assemblies, bool onlyConcreteClasses = true)
  79. {
  80. var result = new List<Type>();
  81. try
  82. {
  83. foreach (var a in assemblies)
  84. {
  85. Type[] types = null;
  86. types = a.GetTypes();
  87. if (types == null)
  88. continue;
  89.  
  90. foreach (var t in types)
  91. {
  92. if (!assignTypeFrom.IsAssignableFrom(t) && (!assignTypeFrom.IsGenericTypeDefinition || !DoesTypeImplementOpenGeneric(t, assignTypeFrom)))
  93. continue;
  94.  
  95. if (t.IsInterface)
  96. continue;
  97.  
  98. if (onlyConcreteClasses)
  99. {
  100. if (t.IsClass && !t.IsAbstract)
  101. {
  102. result.Add(t);
  103. }
  104. }
  105. else
  106. {
  107. result.Add(t);
  108. }
  109. }
  110. }
  111. }
  112. catch (ReflectionTypeLoadException ex)
  113. {
  114. var msg = string.Empty;
  115. foreach (var e in ex.LoaderExceptions)
  116. msg += e.Message + Environment.NewLine;
  117.  
  118. var fail = new Exception(msg, ex);
  119. Debug.WriteLine(fail.Message, fail);
  120.  
  121. throw fail;
  122. }
  123. return result;
  124. }
  125.  
  126. // <summary>
  127. /// Does type implement generic?
  128. /// </summary>
  129. /// <param name="type"></param>
  130. /// <param name="openGeneric"></param>
  131. /// <returns></returns>
  132. protected virtual bool DoesTypeImplementOpenGeneric(Type type, Type openGeneric)
  133. {
  134. try
  135. {
  136. var genericTypeDefinition = openGeneric.GetGenericTypeDefinition();
  137. foreach (var implementedInterface in type.FindInterfaces((objType, objCriteria) => true, null))
  138. {
  139. if (!implementedInterface.IsGenericType)
  140. continue;
  141.  
  142. var isMatch = genericTypeDefinition.IsAssignableFrom(implementedInterface.GetGenericTypeDefinition());
  143. return isMatch;
  144. }
  145.  
  146. return false;
  147. }
  148. catch
  149. {
  150. return false;
  151. }
  152. }
  153.  
  154. /// <summary>Gets the assemblies related to the current implementation.</summary>
  155. /// <returns>A list of assemblies that should be loaded by the Grand factory.</returns>
  156. public virtual IList<Assembly> GetAssemblies()
  157. {
  158. var addedAssemblyNames = new List<string>();
  159. var assemblies = new List<Assembly>();
  160.  
  161. if (LoadAppDomainAssemblies)
  162. AddAssembliesInAppDomain(addedAssemblyNames, assemblies);
  163. AddConfiguredAssemblies(addedAssemblyNames, assemblies);
  164.  
  165. return assemblies;
  166. }
  167.  
  168. #endregion
  169.  
  170. #region Utilities
  171.  
  172. /// <summary>
  173. /// Iterates all assemblies in the AppDomain and if it's name matches the configured patterns add it to our list.
  174. /// </summary>
  175. /// <param name="addedAssemblyNames"></param>
  176. /// <param name="assemblies"></param>
  177. private void AddAssembliesInAppDomain(List<string> addedAssemblyNames, List<Assembly> assemblies)
  178. {
  179. foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
  180. {
  181. if (Matches(assembly.FullName))
  182. {
  183. if (!addedAssemblyNames.Contains(assembly.FullName))
  184. {
  185. assemblies.Add(assembly);
  186. addedAssemblyNames.Add(assembly.FullName);
  187. }
  188. }
  189. }
  190. }
  191.  
  192. /// <summary>
  193. /// Adds specificly configured assemblies.
  194. /// </summary>
  195. /// <param name="addedAssemblyNames"></param>
  196. /// <param name="assemblies"></param>
  197. protected virtual void AddConfiguredAssemblies(List<string> addedAssemblyNames, List<Assembly> assemblies)
  198. {
  199. foreach (string assemblyName in AssemblyNames)
  200. {
  201. Assembly assembly = Assembly.Load(new AssemblyName(assemblyName));
  202. if (!addedAssemblyNames.Contains(assembly.FullName))
  203. {
  204. assemblies.Add(assembly);
  205. addedAssemblyNames.Add(assembly.FullName);
  206. }
  207. }
  208. }
  209.  
  210. /// <summary>
  211. /// Check if a dll is one of the shipped dlls that we know don't need to be investigated.
  212. /// </summary>
  213. /// <param name="assemblyFullName">
  214. /// The name of the assembly to check.
  215. /// </param>
  216. /// <returns>
  217. /// True if the assembly should be loaded into MarkHub.
  218. /// </returns>
  219. public virtual bool Matches(string assemblyFullName)
  220. {
  221. return !Matches(assemblyFullName, AssemblySkipLoadingPattern)
  222. && Matches(assemblyFullName, AssemblyRestrictToLoadingPattern);
  223. }
  224.  
  225. /// <summary>
  226. /// Check if a dll is one of the shipped dlls that we know don't need to be investigated.
  227. /// </summary>
  228. /// <param name="assemblyFullName">
  229. /// The assembly name to match.
  230. /// </param>
  231. /// <param name="pattern">
  232. /// The regular expression pattern to match against the assembly name.
  233. /// </param>
  234. /// <returns>
  235. /// True if the pattern matches the assembly name.
  236. /// </returns>
  237. protected virtual bool Matches(string assemblyFullName, string pattern)
  238. {
  239. return Regex.IsMatch(assemblyFullName, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
  240. }
  241.  
  242. /// <summary>
  243. /// Makes sure matching assemblies in the supplied folder are loaded in the app domain.
  244. /// </summary>
  245. /// <param name="directoryPath">
  246. /// The physical path to a directory containing dlls to load in the app domain.
  247. /// </param>
  248. protected virtual void LoadMatchingAssemblies(string directoryPath)
  249. {
  250. var loadedAssemblyNames = new List<string>();
  251. foreach (Assembly a in GetAssemblies())
  252. {
  253. loadedAssemblyNames.Add(a.FullName);
  254. }
  255.  
  256. if (!Directory.Exists(directoryPath))
  257. {
  258. return;
  259. }
  260.  
  261. foreach (string dllPath in Directory.GetFiles(directoryPath, "*.dll"))
  262. {
  263. try
  264. {
  265. var shadowCopiedAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(dllPath);
  266. }
  267. catch (BadImageFormatException ex)
  268. {
  269. Trace.TraceError(ex.ToString());
  270. }
  271. }
  272. }
  273.  
  274. #endregion
  275. }
  276. }
Add Comment
Please, Sign In to add comment