wsf

wsf

プラグインフレームワークIPlugin

プラグインフレームワーク IPlugin#

Title: プラグインフレームワーク IPlugin

URL Source: https://newlifex.com/core/plugin

Markdown Content:
ビジネス開発でよく使用されるプラグインアーキテクチャの実装、特に外部 DLL 形式のプラグイン。私たちはプラグイン管理の汎用コードを封装しました。

ソースコード:https://github.com/NewLifeX/X/blob/master/NewLife.Core/Model/IPlugin.cs

クイックスタート#

星尘代理 StarAgentは、プラグインをロードして機能を拡張することをサポートしています。以下は、星尘代理がプラグインをロードして初期化するコードです。

// プラグインマネージャー
var pm = _PluginManager = new PluginManager
{
    Identity = "StarAgent",
    Provider = this,

    Log = XTrace.Log,
};
_container.AddSingleton(pm);

// プラグインを起動
WriteLog("プラグイン[{0}]を起動", pm.Identity);
pm.Load();
pm.Init();
foreach (var item in pm.Plugins)
{
    if (item is IAgentPlugin plugin)
    {
        try
        {
            plugin.Start();
        }
        catch (Exception ex)
        {
            XTrace.WriteException(ex);
        }
    }
}

管理クラス PluginManager は、Load でプラグインをロードし、外部 DLL をスキャンすることをサポートします。次に Init がプラグインに初期化作業を通知します。最後に、自分のビジネス操作を実行できます。星尘代理ではここで Start です。

プラグインとは、実際には IPlugin インターフェースを実装するか、PluginAttribute 属性を追加したものです。以下のようになります。

/// <summary>星尘代理プラグイン</summary>
public interface IAgentPlugin : IPlugin
{
    /// <summary>作業を開始</summary>
    public void Start();

    /// <summary>作業を停止</summary>
    /// <param name="reason"></param>
    public void Stop(String reason);
}

/// <summary>星尘代理プラグイン基底クラス</summary>
[Plugin("StarAgent")]
public abstract class AgentPlugin : DisposeBase, IAgentPlugin
{
    /// <summary>サービスプロバイダー</summary>
    public IServiceProvider? Provider { get; set; }

    /// <summary>プラグインを初期化</summary>
    /// <param name="identity"></param>
    /// <param name="provider"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public virtual Boolean Init(String? identity, IServiceProvider provider)
    {
        if (identity != "StarAgent") return false;

        Provider = provider;

        return true;
    }

    /// <summary>作業を開始</summary>
    public virtual void Start() { }

    /// <summary>作業を停止</summary>
    /// <param name="reason"></param>
    public virtual void Stop(String reason) { }
}

コア原理#

汎用プラグインの実装は、一般的にインターフェースまたは属性です。

/// <summary>汎用プラグインインターフェース</summary>
/// <remarks>
/// 簡単な汎用プラグインシステムを構築するために、以下のように規定します:
/// 1、プラグインをロードするホストは、プラグインをロードした後にプラグインのインスタンス化を行います。この時、プラグインのコンストラクタでいくつかのことを行うことができますが、ビジネス処理を開始すべきではありません。なぜならホストの準備作業がまだ完了していない可能性があるからです。
/// 2、ホストがすべての準備を整えた後、プラグインのInitメソッドを順番に呼び出し、ホストの識別子を渡します。プラグインは識別子を通じて自分のターゲットホストを区別します。プラグインのInitはできるだけ早く完了すべきです。
/// 3、プラグインが<see cref="IDisposable"/>インターフェースを実装している場合、ホストは最後にリソースをクリーンアップします。
/// </remarks>
public interface IPlugin
{
    /// <summary>初期化</summary>
    /// <param name="identity">プラグインホスト識別子</param>
    /// <param name="provider">サービスプロバイダー</param>
    /// <returns>初期化が成功したかどうかを返します。現在のホストが期待されるホストでない場合、ここでfalseを返します。</returns>
    Boolean Init(String? identity, IServiceProvider provider);
}

/// <summary>プラグイン属性。特定のプラグイン実装クラスが特定のホストをサポートしているかどうかを判断するために使用されます。</summary>
/// <remarks>インスタンス化</remarks>
/// <param name="identity"></param>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class PluginAttribute(String identity) : Attribute
{
    /// <summary>プラグインホスト識別子</summary>
    public String Identity { get; set; } = identity;
}

プラグインインターフェースは非常にシンプルで、Init のみです。複数のプラグインシステムがある可能性があるため、異なるタイプのプラグインを区別するために、Identity を指定する必要があります。

サービスプロバイダー IServiceProvider も非常に重要で、プラグイン内部でさまざまなサービス実装を取得するのに便利です。

ご覧の通り、私たちの IPlugin インターフェースには Init 初期化のみがあり、破棄のインターフェースはありません。一般的に、プラグインの破棄を示すために IDispose を使用するため、IPlugin は再度そのようなメソッドを定義する必要はありません。

プラグインを管理するために、管理クラス PluginManager を導入します。

  • Identity。現在のプラグイン識別子を指定し、その識別子のプラグインのみをロードします。例えば、前述のクイックスタートコードの StarAgent
  • Provider。ホストのサービスプロバイダー。プラグインは一般的に他のオブジェクトと相互作用する必要があるため、ここが接点になります。
  • Plugins。プラグインコレクション、ロードされたプラグインを保持します。
  • LoadPlugins。プラグインをスキャンし、プラグインコレクションを迅速に取得できます。
  • Load。プラグインをロードし、スキャン後に Plugins コレクションを変更します。
  • Init。プラグインを初期化し、順次プラグインの Init インターフェースを呼び出します。
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。