예제 #1
0
        /// <summary>
        /// Gets an assembly by its AssemblyName.Name
        /// </summary>
        /// <param name="Name">The AssemblyName.Name</param>
        /// <returns>The matching Assembly</returns>
        public static Assembly GetAssemblyByName(string Name)
        {
            if (!AssembliesByName.TryGetValue(Name, out Assembly a))
            {
                a = AppDomain.CurrentDomain.GetAssemblies().First(aa => aa.GetName().Name == Name);
                AssembliesByName.TryAdd(Name, a);
            }

            return(a);
        }
예제 #2
0
        /// <summary>
        /// Since everything is cached, we need to make sure ALL potential assemblies are loaded or we might end up missing classes because
        /// the assembly hasn't been loaded yet. Consider only loading whitelisted references if this is slow
        /// </summary>
        static TypeFactory()
        {
            StaticLogger.Log($"Penguin.Reflection: {Assembly.GetExecutingAssembly().GetName().Version}", StaticLogger.LoggingLevel.Call);

            List <string> failedCache = LoadFailedCache();
            List <string> blacklist;

            if (!TypeFactoryGlobalSettings.DisableFailedLoadSkip)
            {
                blacklist = LoadBlacklistCache();
            }
            else
            {
                blacklist = new List <string>();
            }

            Dictionary <string, Assembly> loadedPaths = new Dictionary <string, Assembly>();

            //Map out the loaded assemblies so we can find them by path
            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (!a.IsDynamic)
                {
                    if (!loadedPaths.ContainsKey(a.Location))
                    {
                        loadedPaths.Add(a.Location, a);
                    }
                }
            }

            List <string> referencedPaths = new List <string>();

            List <string> searchPaths = new List <string>()
            {
                AppDomain.CurrentDomain.BaseDirectory
            };

            if (AppDomain.CurrentDomain.RelativeSearchPath != null)
            {
                searchPaths.Add(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.RelativeSearchPath));
            }

            //We're going to add the paths to the loaded assemblies here so we can double
            //back and ensure we're building the dependencies for the loaded assemblies that
            //do NOT reside in the EXE/Bin directories
            HashSet <string> SearchedPaths = new HashSet <string>();

            foreach (string searchPath in searchPaths)
            {
                StaticLogger.Log($"RE: Dynamically loading assemblys from {searchPath}", StaticLogger.LoggingLevel.Call);

                referencedPaths.AddRange(Directory.GetFiles(searchPath, "*.dll"));

                referencedPaths.AddRange(Directory.GetFiles(searchPath, "*.exe"));

                foreach (string loadPath in referencedPaths)
                {
                    SearchedPaths.Add(loadPath);

                    //If we're not already loaded
                    if (!loadedPaths.TryGetValue(loadPath, out Assembly a))
                    {
                        if (failedCache.Contains(loadPath))
                        {
                            StaticLogger.Log($"RE: Skipping due {FAILED_CACHE}: {loadPath}", StaticLogger.LoggingLevel.Call);
                            continue;
                        }

                        //Check for blacklist
                        string matchingLine = blacklist.FirstOrDefault(b => Regex.IsMatch(Path.GetFileName(loadPath), b));
                        if (!string.IsNullOrWhiteSpace(matchingLine))
                        {
                            StaticLogger.Log($"RE: Skipping assembly due to blacklist match ({matchingLine}) {loadPath}", StaticLogger.LoggingLevel.Call);

                            continue;
                        }

                        StaticLogger.Log($"RE: Dynamically loading assembly {loadPath}", StaticLogger.LoggingLevel.Call);

                        try
                        {
                            AssemblyName an = AssemblyName.GetAssemblyName(loadPath);

                            a = LoadAssembly(loadPath, an, true);

                            AssembliesByName.TryAdd(an.Name, a);
                        }
                        catch (Exception ex)
                        {
                            StaticLogger.Log(ex.Message, StaticLogger.LoggingLevel.Call);
                            StaticLogger.Log(ex.StackTrace, StaticLogger.LoggingLevel.Call);

                            failedCache.Add(loadPath);
                        }
                    }

                    if (!(a is null))
                    {
                        AddReferenceInformation(a);
                    }
                }
            }

            //And now we double check to make sure we're not missing anything in the loaded
            //assemblies that were not found in our path discovery
            foreach (KeyValuePair <string, Assembly> kvp in loadedPaths)
            {
                if (!SearchedPaths.Contains(kvp.Key))
                {
                    AddReferenceInformation(kvp.Value);
                }
            }

            StaticLogger.Log($"RE: {nameof(TypeFactory)} static initialization completed", StaticLogger.LoggingLevel.Final);

            try
            {
                AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad;

                List <Assembly> CurrentlyLoadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();

                foreach (Assembly assembly in CurrentlyLoadedAssemblies)
                {
                    if (!assembly.IsDynamic)
                    {
                        CheckLoadingPath(assembly.Location);
                    }
                }
            }
            catch (SecurityException ex)
            {
                StaticLogger.Log($"RE: A security exception was thrown attempting to subscribe to assembly load events: {ex.Message}", StaticLogger.LoggingLevel.Final);
            }

            if (!TypeFactoryGlobalSettings.DisableFailedLoadSkip)
            {
                File.WriteAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FAILED_CACHE), failedCache);
            }
        }