// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; using System.IO; using System.Linq; using System.Reflection; using Languages.Facade; namespace Languages.Integration { /// /// Модуль с функциями загрузки поддерживаемых языков программирования /// public static class LanguageIntegrator { private static readonly LanguageProvider LanguageProvider = LanguageProvider.Instance; /// /// Имя директории, содержащей установленные плагины языков программирования /// private const string languageKitsDirectoryName = "LanguageKits"; /// /// Событие, информирующее об успешной загрузке плагина языка /// public static event Action LanguageLoaded; /// /// Событие, информирующее об ошибке загрузки плагина языка /// public static event Action LanguageLoadErrorOccured; /// /// Возвращает директорию, содержащую комплекты языков (если ее нет, то вернется null) /// private static DirectoryInfo GetLanguageKitsDirectory() { string binDirectoryPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string languageKitsDirectoryPath = Path.Combine(binDirectoryPath, languageKitsDirectoryName); if (Directory.Exists(languageKitsDirectoryPath)) return new DirectoryInfo(languageKitsDirectoryPath); return null; } /// /// Загружает все языковые комплекты для использования (имя "главной" dll должно заканчиваться на Language) /// public static void LoadAllLanguageKits() { DirectoryInfo languageKitsDirectory = GetLanguageKitsDirectory(); if (languageKitsDirectory == null) return; foreach (var languageKit in languageKitsDirectory.GetDirectories()) { FileInfo[] dllFiles = languageKit.GetFiles(); foreach (var dll in dllFiles) { if (dll.Name.EndsWith("Language.dll")) { IntegrateLanguageFromAssembly(dll); break; } } } } /// /// Загружает все языки, доступные в системе /// public static void LoadAllLanguages() { LoadStandardLanguages(); LoadAllLanguageKits(); } /// /// Загружает стандартные языки платформы из папки bin /// public static void LoadStandardLanguages() { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName); DirectoryInfo directory = new DirectoryInfo(directoryName); FileInfo[] dllFiles = directory.GetFiles("*Language.dll"); foreach (FileInfo languageFile in dllFiles) { IntegrateLanguageFromAssembly(languageFile); } } /// /// Загружает плагин языка из dll, содержащей класс, представляющий язык /// (класс должен реализовывать интерфейс ILanguage и его имя должно заканчиваться на Language) /// /// dll, содержащая язык private static void IntegrateLanguageFromAssembly(FileInfo languageFile) { try { ILanguage languageFound = InstantiateLanguageAndAddToLanguagesList(languageFile); if (languageFound == null) { throw new Exception("Language class wasn't found in language assembly. (To be found it should contain 'Language' in it's name)"); } LanguageLoaded?.Invoke(languageFound); } catch (ReflectionTypeLoadException e) { #if DEBUG string errorMessage = e + Environment.NewLine; errorMessage += ":" + Environment.NewLine; errorMessage += string.Join(Environment.NewLine, e.LoaderExceptions.Select(error => error.ToString())) + Environment.NewLine; File.AppendAllText("log.txt", errorMessage); #endif LanguageLoadErrorOccured?.Invoke(languageFile.Name); } catch (Exception e) { #if DEBUG string errorMessage = e + Environment.NewLine; File.AppendAllText("log.txt", errorMessage); #endif LanguageLoadErrorOccured?.Invoke(languageFile.Name); } } /// /// Конструирует объект языка и добавляет его в список языков в LanguageProvider /// /// /// private static ILanguage InstantiateLanguageAndAddToLanguagesList(FileInfo languageFile) { Assembly assembly = Assembly.LoadFile(languageFile.FullName); Type[] types = assembly.GetTypes(); ILanguage languageFound = null; foreach (Type type in types) { if (type.Name.EndsWith("Language") && type.IsClass) { object obj = Activator.CreateInstance(type); if (obj is ILanguage language) { languageFound = language; LanguageProvider.Languages.Add(language); } break; } } return languageFound; } } }