Как предоставить другую стратегию загрузки сборок приложений в загрузчике Kephas - PullRequest
0 голосов
/ 05 марта 2019

Реализация по умолчанию загрузки сборок приложения в приложение Kephas состоит в том, чтобы включить все сборки, найденные в папке приложения.Что если мне нужно предоставить другую папку или я хочу поддерживать плагины?Как указать другую папку или список папок для поиска?

1 Ответ

0 голосов
/ 06 марта 2019

Почти все в Kephas настраивается, и служба IAppRuntime не является исключением.Однако, в отличие от обычных служб приложений, это не регистрируется с помощью атрибута [AppServiceContract], а устанавливается и настраивается во время процедуры начальной загрузки.Основная причина такого поведения заключается в том, что служба IAppRuntime требуется перед инициализацией контейнера композиции / IoC.

Возможная реализация приведена ниже:

/// <summary>
/// An application runtime supporting plugins.
/// Each plugin is found in its own folder in the Plugins sub directory of the application root folder.
/// </summary>
public class PluginsAppRuntime : DefaultAppRuntime
{
    /// <summary>
    /// Initializes a new instance of the <see cref="PluginsAppRuntime"/> class.
    /// </summary>
    /// <param name="assemblyLoader">Optional. The assembly loader.</param>
    /// <param name="logManager">Optional. The log manager.</param>
    /// <param name="assemblyFilter">Optional. A filter for loaded assemblies.</param>
    /// <param name="appLocation">Optional. The application location. If not specified, the current
    ///                           application location is considered.</param>
    public PluginsAppRuntime(
        IAssemblyLoader assemblyLoader = null,
        ILogManager logManager = null,
        Func<AssemblyName, bool> assemblyFilter = null,
        string appLocation = null)
        : base(assemblyLoader, logManager, assemblyFilter, appLocation)
    {
        pluginsFolder = Path.Combine(this.GetAppLocation(), "Plugins");
        this.PluginsFolder = Path.GetFullPath(pluginsFolder);
    }

    /// <summary>
    /// Gets the pathname of the plugins folder.
    /// </summary>
    public string PluginsFolder { get; }

    /// <summary>
    /// Enumerates the application directories containing assemblies to be loaded.
    /// </summary>
    protected override IEnumerable<string> GetAppAssemblyDirectories()
    {
        var rootDirectory = this.GetAppLocation();
        var appDirectories = new List<string> { rootDirectory };

        appDirectories.AddRange(this.EnumeratePluginFolders());

        var logger = this.GetLogger();
        logger.Info($"Loading application from directories: {string.Join(", ", appDirectories)}");

        return appDirectories;
    }

    /// <summary>
    /// Enumerates the root bin folders for the plugins.
    /// </summary>
    public IEnumerable<string> EnumeratePluginFolders()
    {
        var binPluginsFolder = this.PluginsFolder;

        if (Directory.Exists(binPluginsFolder))
        {
            var pluginsDirectories = Directory.EnumerateDirectories(binPluginsFolder);
            return pluginsDirectories;
        }

        return new string[0];
    }
}

/// <summary>
/// For the sake of simplicity, add an extension method to the ambient services builder to make use of this new service.
/// </summary>
public static class PluginsAmbientServicesBuilderExtensions
{
    /// <summary>
    /// Sets the plugins-enabled application runtime to the ambient services.
    /// </summary>
    /// <param name="ambientServicesBuilder">The ambient services builder.</param>
    /// <param name="assemblyFilter">Optional. A filter specifying the assembly (optional).</param>
    /// <param name="appLocation">Optional. The application location (optional). If not specified, the
    ///                           assembly location is used.</param>
    /// <returns>
    /// The provided ambient services builder.
    /// </returns>
    public static AmbientServicesBuilder WithPluginsAppRuntime(
        this AmbientServicesBuilder ambientServicesBuilder,
        Func<AssemblyName, bool> assemblyFilter = null,
        string appLocation = null)
    {
        Requires.NotNull(ambientServicesBuilder, nameof(ambientServicesBuilder));

        var ambientServices = ambientServicesBuilder.AmbientServices;
        var assemblyLoader = new DefaultAssemblyLoader();
        ambientServices.RegisterService<IAssemblyLoader>(assemblyLoader);

        return ambientServicesBuilder.WithAppRuntime(
            new PluginsAppRuntime(
                assemblyLoader,
                ambientServices.LogManager,
                assemblyFilter: assemblyFilter,
                appLocation: appLocation));
    }
}

/// <summary>
/// Last, but not least, define the application root object.
/// </summary>
public class App : AppBase
{
    /// <summary>Configures the ambient services asynchronously.</summary>
    /// <param name="appArgs">The application arguments.</param>
    /// <param name="ambientServicesBuilder">The ambient services builder.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>The asynchronous result.</returns>
    protected override async Task ConfigureAmbientServicesAsync(
        string[] appArgs,
        AmbientServicesBuilder ambientServicesBuilder,
        CancellationToken cancellationToken)
    {
        ambientServicesBuilder
            .WithAppConfiguration(new DefaultAppConfiguration())
            .WithPluginsAppRuntime()
            .WithMefCompositionContainer();
    }
}

/// <summary>
/// Now everything is ready to go!
/// </summary>
public static class Program
{
    private static async Task<int> Main(string[] args)
    {
        try
        {
            var result = await new App().BootstrapAsync(args).PreserveThreadContext();
            return 0;
        }
        catch (Exception ex)
        {
            return 100;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...