// 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;
}
}
}