C#/VB.NETでプロデルプラグインを作る方法

プロデルのプラグインは、 C#やVB.NETなどの.NET Frameworkを利用したプログラミング環境で開発できます。この記事では、Visual Studioを使ってプロデルプラグインを作る方法をご説明します。

なおこの記事は、プロデル1.6を前提に書かれています。プロデルの内部仕様は頻繁に手を加えているため、この記事を投稿後に仕様が変わっている可能性もあります。仕様変更があった場合にはできるだけ記事にも反映される予定ですが、ご容赦ください。

また説明にはプロデル言語の用語を使っていますので、この記事を読む前にすでにブログで説明している手順や補語に関する説明をご覧下さい。

プラグインを作るには

プロデルプラグインは、 C#のクラスライブラリ(.dllファイル)で作られています。この記事ではC#言語を使いますが、同じ.NET FrameworkであるVB.NET言語でも作ることができます。(VB.NET用のひな形も用意しています)

次のリンクにてプロデルプラグインのひな形を用意しています。ひな形をもとに作ると簡単です。

https://produ.irelang.jp/downloads/developer.html

GitHubのレポジトリも用意していますので、こちらからクローンを作ることもできます。

https://github.com/utopiat-ire/RdrPluginTemplate

C#などでプロデルプラグインを作る場合には、utopiat.Host.dllというファイルを参照します。このDLLファイルには、プラグインを定義するために必要なクラスが用意されています。プロデル本体は、Produire.Core.dllですが、プラグインを作る時にはこれを継承する必要はありません。

種類を定義する

種類には、2つのタイプがあります。

  • 生成可能種類(IProduireClassインタフェイス)
  • 静的種類(IProduireStaticClassインタフェイス)

生成可能種類は、「作る」文でインスタンスを生成できる種類です。「ボタン」や「スタック」などの種類が生成可能種類です。静的種類は、その種類名を指定するだけで呼び出せるシングルトンの種類です。「ファイル」や「HTTP」 などの種類が静的種類です。この2つのタイプは、それぞれのインタフェイスを実装することで指定します。なお2つのインタフェイスには、実装すべきメソッドやプロパティはありません。

まずは、C#言語で「静的種類」を定義する例を紹介します。次のプログラムをコンパイルしてください。ここではコンパイル後のファイル名を「RdrPluginSample.dll」とします。

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Produire; // utopiat.Host.dllを参照すること

namespace RdrPluginSample
{
	// 静的種類の例
	public class 静的型サンプル : IProduireStaticClass // これを実装しないとプロデルから利用できない
	{
		// 手順
		[自分("で")]
		public void テストする([を]string 名前)
		{
			MessageBox.Show(名前 + "さん、こんにちは!");
		}
	}
}

コンパイルしたプラグインは、プロデルで次のように呼び出せます。プロデルファイルと同じフォルダにあるDLLファイルは、自動的に読み込まれるため、DLLファイルと同じフォルダにある場合には、「利用する」文を書く必要ありません。

「RdrPluginSample.dll」を利用する
静的型サンプルで「太郎」をテストする

次にインスタンスを生成可能な「生成可能種類」の例です。

	// 生成可能な種類の例
	public class 生成型サンプル : IProduireClass // これを実装しないとプロデルから利用できない
	{
		private string name;

		public 生成型サンプル()
		{
			name = "名無し";
		}
		public 生成型サンプル(string 名前)
		{
			this.name = 名前;
		}

		// 手順
		[自分("が")]
		public void 挨拶する()
		{
			MessageBox.Show(name + "さん、こんにちは!");
		}

		// 設定項目
		public string 名前
		{
			get { return name; }
			set { name = value; }
		}
	}

コンパイルしたプラグインは、プロデルで次のように呼び出せます。 「生成可能種類」ですので「作る」文でインスタンスを作ってから手順や設定項目にアクセスします。

「RdrPluginSample.dll」を利用する
太郎さんという生成型サンプルを作る
太郎さんの名前は、「太郎」
太郎さんの名前を表示する
太郎さんが挨拶する

花子さんという生成型サンプル(「花子」)を作る
花子さんの名前を表示する
花子さんが挨拶する

手順を定義する

プロデルの手順を宣言するには、 C#のメソッドを定義して、定義の冒頭に [手順Attribute] 属性を加えます。

メソッドの仮引数には、属性(Attribute)を使って一つ一つ助詞を定義しておきます。プロデルからメソッドを呼ぶときに、それぞれ助詞に対応する仮引数へ値が指定されて呼び出されます。プロデルでは助詞によって仮引数が対応付けられるため、C#のメソッドの引数の順番と、プロデルの手順呼び出しの実補語の順番が一致している必要はありません。

public void テストする([を]string 名前)

この例では、「~を」実補語で指定した値が、「名前」仮引数に渡されます。

引数の助詞

プロデルでは 助詞Attributeに任意の文字列を助詞として定義できます。よく使われる助詞については、助詞Attributeクラスを継承した 「をAttribute」 「へAttribute」クラスなどのクラスが定義されていますので、より簡潔に書けます。

あらかじめ用意されている助詞Attributeクラスを継承するクラス

を, へ(に), で, と, が, として, という, から, まで, だけ, 文字, をと

なお、これらの語には、助詞として分類されない助数詞や数詞などや複数の語が組み合わされた字句もありますが、プロデルでは便宜的にすべて「助詞」と呼んでしまっています。

またレシーバ補語となる助詞を示す自分Attributeクラスを継承したクラスも用意されています。

自分を, 自分へ, 自分から, 自分で, 自分が

助詞に「の」を指定することもできますが、制約があります。

  • メソッドに[名詞手順Attribute]を付ける
  • 引数に[既定Attribute]を付ける。
  • レシーバ補語の助詞は「の」のみ

「~の」を助詞として含めることができるのは、「名詞型手順のみ」です。これは「の」が設定項目の区切りを表すことに使われているため、正しく構文解析されるように普通の手順とは区別して扱う必要があるためです。

例えば「二進数」という名前の手順を宣言する場合には、次のように定義します。

public class 進数計算
{
	[自分("の"), 名詞手順]
	public string 二進数([既定]int 値)
	{

	}
}

名詞手順の場合、レシーバ補語も「の」のみとなります。つまり 『【値】の【レシーバ】の【手順名】』の形式で書く必要があります。

10の進数計算の二進数を報告する

また、名詞手順は、『【レシーバ】:【手順名】(【値】)』の形式で書くこともできます。

[進数計算:二進数(10)]を報告する

名詞手順には「~の」以外の助詞を含めることもできます。その場合、手順呼び出し文では、「【値】の」よりも前に実補語を書く必要があります。

    [手順名("要素を", "取得する")]
    public ウェブブラウザ要素 要素を取得する([自分連体詞("から")]Point 位置)
    {
        HtmlElement item = document.GetElementFromPoint(位置);
        return ウェブブラウザ要素.Create(item);
    }

設定項目を定義する

プロパティは設定項目として扱われますが、プロデル上での設定項目名とC#上でのプロパティ名を分けて宣言することもできます。別名で設定項目を宣言するにはプロパティ定義の冒頭に [設定項目Attribute] 属性(Attribute)を加えます。

5桁で10の進数計算の二進数を報告する

ラッパー種類

ラッパー種類の場合は、型パラメータで指定した型のインスタンスがプロデル内で扱われたときに、ここで定義したラッパー種類がプロデル内部で生成され、プロデル種類として手順や設定項目へアクセスできるようになります。すでに用意されているライブラリをプロデルでそのまま使いたい場合や、継承できないクラスをプロデルの種類として定義したい場合には、このような ClassWarpperジェネリッククラスが便利です。

public class テキストベース : ClassWarpper<TextBoxBase>
{
	[説明(@"テキストの内容")]
	public string 内容
	{
		get { return baseObject.Text; }
		set { baseObject.Text = value; }
	}
}

部品を定義する

部品(コントロール)種類を定義したい場合には、宣言するクラスにSystem.Windows.Forms.Controlクラスを継承しIProduireClassインタフェイスを実装してください。Controlクラスを継承するクラスは、プロデルでも部品として利用できます。この場合、「大きさ」設定項目や「内容」設定項目など「部品の基本形」種類で定義された設定項目や手順は、プラグインで定義した部品でも利用できます。

GitHubでは、Windows Media Playerの機能をプロデルから利用するためのプラグインのソースコードをコミットしています。プロデルプラグインの基本的な定義方法を一通り利用していますので、参考にチェックアウトしてもらえたら嬉しいです。

https://github.com/utopiat-ire/RdrWMPPlugin

例えば、既存の.NET Frameworkのコントロールをプロデルで利用する場合には、そのクラスを継承した新しいクラスを宣言することで利用できます。

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Produire;

namespace RdrPluginSample
{
	// 部品種類の例
	public class 部品サンプル : Button, IProduireClass
	{
		public 部品サンプル()
		{
			Text = "プラグインボタン";
		}
	}
}

部品クラスがsealedクラスとなっているなどして継承できない場合には、ClassWarpperジェネリッククラスを利用すると便利です。

イベント手順

イベント手順を定義する場合は、C#言語のイベント定義に則って定義します。EventArgクラスの値をプロデルの「この時」変数で利用したい場合には、 EventArgクラスを継承したProduireEventArgsクラスを使います。ProduireEventArgs<T>クラスを使うことでより簡潔に定義できます。

データ型について

プロデルプラグインを定義する際、stringやintなどの.NET Frameworkの基本的なデータ型については、自動的にプロデルの内部型へ変換されます。

値型(クラス名)プロデル型値型か
string文字列 値型
int整数 値型
long長整数 値型
float浮動小数 値型
double倍浮動小数 値型
System.Decimal固定小数
byte[]バイナリデータ
bool真偽値 値型
System.DateTime日時形式 値型
System.TimeSapn日時期間形式 値型
System.Drawing.Color色情報 値型
System.Drawing.Sizeサイズ 値型
System.Drawing.SizeF浮動小数サイズ 値型
System.Drawing.Point座標 値型
System.Drawing.PointF浮動小数座標 値型
System.Drawing.Rectangle矩形 値型
System.Drawing.Image画像
System.Drawing.Iconプロデルアイコン
System.Array配列
IDictionary辞書

なお、配列型や辞書型の場合は、呼び出し時に新しいインスタンスが生成されて、要素のデータ型についても変換されます。なお、データ型を変換する際に「値型」以外のクラスについてはプロデル内部で新しいインスタンスが生成されてコピーされます。型変換が多数発生する場合にはパフォーマンスにご注意下さい。

列挙体

列挙体についてもC#で宣言したいものをそのまま利用できます。ただ他のクラスを移植する場合などで英単語で構成される列挙体の項目名を日本語に置き換えたい場合があります。この場合、[列挙体Attribute]を付加した列挙体を宣言することで、既存の列挙体をプロデルでの名称に置き換えて宣言することができます。

例えば、すでに別のクラスライブラリで宣言されたWMPPlayState列挙体を、それに対応するプロデル上として宣言したい場合には、次のように宣言します。

	[列挙体(typeof(WMPPlayState))]
	public enum 再生状態
	{
		再生中 = WMPPlayState.wmppsPlaying,
		停止中 = WMPPlayState.wmppsStopped,
		バッファリング中 = WMPPlayState.wmppsBuffering,
		一時停止中 = WMPPlayState.wmppsPaused,
		準備完了 = WMPPlayState.wmppsReady,
		再生終了 = WMPPlayState.wmppsMediaEnded,
		再接続中 = WMPPlayState.wmppsReconnecting,
		待機中 = WMPPlayState.wmppsWaiting,
		再生準備中 = WMPPlayState.wmppsTransitioning,
		最後 = WMPPlayState.wmppsLast
	}

メソッドやプロパティでデータ型がWMPPlayStateの列挙値である値を、プロデル上で扱うときには「再生状態」列挙体と同じと見なして対応する値へ自動的に変換します。

そのほかの属性

それぞれの定義には他にも次のよう属性が用意されています。

説明Attribute

ウィンドウの設計画面やコードヒントなどで表示する説明文です。

除外Attribute

この定義をプロデルの手順や設定項目として扱わないことを表します。この定義は、プロデル上では呼び出したりアクセスすることはできません。

非表示Attribute

ウィンドウの設計画面や入力補完機能で表示しないことを表します。非推奨の定義などに使います。プログラム上で呼び出したりアクセスすることはできます。

非生成Attribute

ウィンドウの設計画面で生成しない定義を表します。プログラムを生成するときにこの定義は、スキップされます。実行時にのみ意味がある設定項目や、他の設定項目と同一の値が含まれるときなどに指定します。

プロデルプラグインでしたいことができるように

プロデルに対応していない.NET Frameworkのクラスライブラリを利用できます。C#などでしか使えなかった機能をプロデルでも利用できるようになります。

ご覧の通りプロデルプラグインは、通常のC#のクラスライブラリでもありますので、C#とプロデルで共通利用できるDLLファイルを作ることもできます。

C#言語を知っている方はぜひプロデルのプラグイン作りにも挑戦してみて下さい!心待ちにしています。

  • いいね (2)
  • 続編を読みたい (2)

コメントを残す