.NETプログラミング研究 第40号 †
.NET Tips †
プラグイン機能を持つアプリケーションを作成する - その2 †
(お詫び)今回はコードがかなり長くなってしまいました。ご了承ください。
前回の「プラグイン機能を持つアプリケーションを作成する - その1」ではプラグイン機能を実現させるための基本的な考え方について説明しました。簡単に復習すると、その方法とは、インターフェイスを使用するというものでした。詳細は前回のメールマガジンでご確認ください。
今回はさらに実用的な例として、Windowsアプリケーションでプラグイン機能を実現する方法を考えます。ここでは具体的に、プラグインの使用できる簡単なエディタを作成します。
あくまでプラグイン機能を説明することが目的ですので、エディタは思い切り単純にし、フォームにRichTextBoxとMainMenuのみを配置することにします。プラグインからエディタのRichTextBoxコントロールにアクセスすることにより、プラグインの機能が果たせるようにします。
インターフェイスを定義する †
前回と同じように、まずプラグインのクラスが実装すべきインターフェイスを定義します。今回はプラグインのインターフェイスに加えて、プラグインを使用するホストの側が実装すべきインターフェイスも定義することにします。ホストのためのインターフェイスでは、プラグインのホストとして必要な機能をメンバとして定義し、プラグインからこのメンバを通してホストにアクセスできるようにします。
具体的には、プラグインから指定されたメッセージをホストで表示するためのメソッドと、ホストのRichTextBoxコントロールを取得するためのプロパティ、さらにホストのメインフォームを取得するためのプロパティを定義することにします。
それでは実際にこれらのインターフェイスを作成してみましょう。前号と同様、クラスライブラリとして作成するため、Visual Studio .NETではクラスライブラリのプロジェクトを作成し("Plugin"という名前で作成しています)、.NET SDKでは/target:libraryコンパイラオプションを使用します。また、アセンブリファイル名は、"Plugin.dll"とします。さらに今回はWindowsアプリケーションを扱うため、"System.Windows.Forms.dll"を参照に追加します。(参照に追加するには、Visual Studio .NETの場合は、ソリューションエクスプローラの「参照設定」を、.NET SDKの場合は、/referenceコンパイラオプションを使用します。)
コードは、次のようになります。IPluginインターフェイスがプラグインのためのインターフェイスで、IPluginHostインターフェイスがプラグインのホストのためのインターフェイスです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
| | Imports System
Imports System.Windows.Forms
Namespace Plugin
Public Interface IPlugin
ReadOnly Property Name() As String
ReadOnly Property Version() As String
ReadOnly Property Description() As String
Property Host() As IPluginHost
Sub Run()
End Interface
Public Interface IPluginHost
ReadOnly Property MainForm() As Form
ReadOnly Property RichTextBox() As RichTextBox
Sub ShowMessage(ByVal plugin As IPlugin, ByVal msg As String)
End Interface
End Namespace
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
| | using System;
using System.Windows.Forms;
namespace Plugin
{
public interface IPlugin
{
string Name {get;}
string Version {get;}
string Description {get;}
IPluginHost Host {get; set;}
void Run();
}
public interface IPluginHost
{
Form MainForm {get;}
RichTextBox RichTextBox {get;}
void ShowMessage(IPlugin plugin, string msg);
}
}
|
IPluginは前回と比べ、プラグインのバージョンと説明を取得するためのプロパティが新たに追加され、さらに、Runメソッドもパラメータ、返り値がなくなりました。また、IPluginHostを設定、取得するためのプロパティも加えられています。
プラグインを作成する †
次に、IPluginインターフェイスを実装したプラグインのクラスを作成します。ここでは、RichTextBox内の文字数を表示するプラグイン(CountCharsクラス)を作成してみましょう。
プラグインも前号と同様に、クラスライブラリとして作成し、"Plugin.dll"を参照に追加します。また、"System.Windows.Forms.dll"も参照に追加してください。出力するアセンブリファイル名は、"CountChars.dll"とします。(Visual Studio .NETのVB.NETの場合は、プロジェクトのプロパティの「ルート名前空間」が空白になっているものとします。デフォルトではプロジェクト名となっていますので、変更する必要があります。)
CountCharsクラスのコードは次のようになります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
| | Imports System
Namespace CountChars
Public Class CountChars
Implements Plugin.IPlugin
Private _host As Plugin.IPluginHost
Public ReadOnly Property Name() As String _
Implements Plugin.IPlugin.Name
Get
Return "文字数取得"
End Get
End Property
Public ReadOnly Property Version() As String _
Implements Plugin.IPlugin.Version
Get
Dim asm As System.Reflection.Assembly = _
System.Reflection.Assembly.GetExecutingAssembly()
Dim ver As System.Version = asm.GetName().Version
Return ver.ToString()
End Get
End Property
Public ReadOnly Property Description() As String _
Implements Plugin.IPlugin.Description
Get
Return "エディタで編集中の文章の文字数を表示します。"
End Get
End Property
Public Property Host() As Plugin.IPluginHost _
Implements Plugin.IPlugin.Host
Get
Return Me._host
End Get
Set(ByVal Value As Plugin.IPluginHost)
Me._host = Value
End Set
End Property
Public Sub Run() Implements Plugin.IPlugin.Run
Dim msg As String = String.Format("文字数 : {0} 文字", _
Me._host.RichTextBox.Text.Length)
Me._host.ShowMessage(Me, msg)
End Sub
End Class
End Namespace
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
| | using System;
namespace CountChars
{
public class CountChars : Plugin.IPlugin
{
private Plugin.IPluginHost _host;
public string Name
{
get
{
return "文字数取得";
}
}
public string Version
{
get
{
System.Reflection.Assembly asm =
System.Reflection.Assembly.GetExecutingAssembly();
System.Version ver = asm.GetName().Version;
return ver.ToString();
}
}
public string Description
{
get
{
return "エディタで編集中の文章の文字数を表示します。";
}
}
public Plugin.IPluginHost Host
{
get
{
return this._host;
}
set
{
this._host = value;
}
}
public void Run()
{
string msg =
string.Format("文字数 : {0} 文字",
this._host.RichTextBox.Text.Length);
this._host.ShowMessage(this, msg);
}
}
}
|
特に説明を必要とする箇所はないでしょう。Runメソッドでは、IPluginHostオブジェクトからRichTextBoxにアクセスし、文字数を取得し、IPluginHostのShowMessageメソッドで結果をホストで表示しています。
ウィンドウを表示するプラグインの作成 †
次にWindowsアプリケーションらしく、ウィンドウを表示するプラグインを作成してみましょう。ここでは、「検索」ウィンドウにより、RichTextBoxから指定された文字列を検索するプラグインを作ります(エディタとしては、プラグインで処理する機能ではありませんが)。
まず、CountCharsクラスと同様、クラスライブラリのプロジェクトを作成し(名前は、"FindString"とします)、"Plugin.dll"と"System.Windows.Forms.dll"を参照に追加します("System.Windows.Forms.dll"は今追加しなくても、「Windowsフォームの追加」でプロジェクトにフォームを追加すれば、自動的に追加されます)。
続いて、「Windowsフォームの追加」でプロジェクトにフォーム(FindForm)を追加し、「検索」ウィンドウを作成します。このフォームに配置するコントロール及び、変更するプロパティ(あるいはイベント)の一覧は次のようになります。
コントロール: Form
Name: FindForm
Text: 検索
AcceptButton: findButton
CancelButton: closeButton
FormBorderStyle: FixedToolWindow
ShowInTaskbar: false
コントロール: TextBox
Name: findString
Text: ""
コントロール: Button
Name: findButton
Text: 次を検索
DialogResult: OK
Clickイベント: findButton_Click
コントロール: Button
Name: closeButton
Text: 閉じる
DialogResult: Cancel
Clickイベント: closeButton_Click
コントロール: CheckBox
Name: wholeWord
Text: 単語単位で検索する
コントロール: CheckBox
Name: matchCase
Text: 大文字小文字を区別する
コントロール: CheckBox
Name: reverse
Text: 上へ検索する
さらに、FindFormクラスに次のコードを追加し、指定されたRichTextBoxを検索できるようにします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
| |
Friend RichTextBox As RichTextBox
Private Sub findButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles findButton.Click
Dim finds As RichTextBoxFinds = RichTextBoxFinds.None
If Me.wholeWord.Checked Then
finds = finds Or RichTextBoxFinds.WholeWord
End If
If Me.matchCase.Checked Then
finds = finds Or RichTextBoxFinds.MatchCase
End If
If Me.reverse.Checked Then
finds = finds Or RichTextBoxFinds.Reverse
End If
Dim startPos, endPos As Integer
If Not Me.reverse.Checked Then
startPos = Me.RichTextBox.SelectionStart + _
Me.RichTextBox.SelectionLength
endPos = -1
If startPos >= Me.RichTextBox.TextLength Then
MessageBox.Show("検索が完了しました。", "検索")
Return
End If
Else
startPos = 0
endPos = Me.RichTextBox.SelectionStart
If endPos <= 0 Then
MessageBox.Show("検索が完了しました。", "検索")
Return
End If
End If
If Me.RichTextBox.Find( _
findString.Text, startPos, endPos, finds) < 0 Then
MessageBox.Show("検索が完了しました。", "検索")
Else
Me.RichTextBox.Focus()
End If
End Sub
Private Sub closeButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles closeButton.Click
Me.Close()
End Sub
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
| |
internal RichTextBox RichTextBox;
private void findButton_Click(
object sender, System.EventArgs e)
{
RichTextBoxFinds finds = RichTextBoxFinds.None;
if (this.wholeWord.Checked)
finds |= RichTextBoxFinds.WholeWord;
if (this.matchCase.Checked)
finds |= RichTextBoxFinds.MatchCase;
if (this.reverse.Checked)
finds |= RichTextBoxFinds.Reverse;
int startPos, endPos;
if (!this.reverse.Checked)
{
startPos = this.RichTextBox.SelectionStart +
this.RichTextBox.SelectionLength;
endPos = -1;
if (startPos >= this.RichTextBox.TextLength)
{
MessageBox.Show("検索が完了しました。", "検索");
return;
}
}
else
{
startPos = 0;
endPos = this.RichTextBox.SelectionStart;
if (endPos <= 0)
{
MessageBox.Show("検索が完了しました。", "検索");
return;
}
}
if (this.RichTextBox.Find(
findString.Text, startPos, endPos, finds) < 0)
MessageBox.Show("検索が完了しました。", "検索");
else
this.RichTextBox.Focus();
}
private void closeButton_Click(
object sender, System.EventArgs e)
{
this.Close();
}
|
次にこのフォームを表示させるプラグインクラス(FindString)を作成します。コードは、次のようになります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
| | Imports System
Imports System.Windows.Forms
Namespace FindString
Public Class FindString
Implements Plugin.IPlugin
Private _host As Plugin.IPluginHost
Private _mainForm As FindForm
Public ReadOnly Property Name() As String _
Implements Plugin.IPlugin.Name
Get
Return "文字列の検索"
End Get
End Property
Public ReadOnly Property Description() As String _
Implements Plugin.IPlugin.Description
Get
Return "編集中の文章から指定された文字列を検索します。"
End Get
End Property
Public Property Host() As Plugin.IPluginHost _
Implements Plugin.IPlugin.Host
Get
Return _host
End Get
Set(ByVal Value As Plugin.IPluginHost)
_host = Value
End Set
End Property
Public ReadOnly Property Version() As String _
Implements Plugin.IPlugin.Version
Get
Dim asm As System.Reflection.Assembly = _
System.Reflection.Assembly.GetExecutingAssembly()
Dim ver As System.Version = asm.GetName().Version
Return ver.ToString()
End Get
End Property
Public Sub Run() Implements Plugin.IPlugin.Run
If Not (Me._mainForm Is Nothing) AndAlso _
Not Me._mainForm.IsDisposed Then
Me._mainForm.Activate()
Return
End If
Me._mainForm = New FindForm
Me._mainForm.RichTextBox = Me._host.RichTextBox
Me._mainForm.Owner = Me._host.MainForm
Me._mainForm.Show()
End Sub
End Class
End Namespace
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
| | using System;
using System.Windows.Forms;
namespace FindString
{
public class FindString : Plugin.IPlugin
{
private Plugin.IPluginHost _host;
private FindForm _mainForm;
public string Name
{
get
{
return "文字列の検索";
}
}
public string Description
{
get
{
return "編集中の文章から指定された文字列を検索します。";
}
}
public Plugin.IPluginHost Host
{
get
{
return _host;
}
set
{
_host = value;
}
}
public string Version
{
get
{
System.Reflection.Assembly asm =
System.Reflection.Assembly.GetExecutingAssembly();
System.Version ver = asm.GetName().Version;
return ver.ToString();
}
}
public void Run()
{
if (this._mainForm != null && !this._mainForm.IsDisposed)
{
this._mainForm.Activate();
return;
}
this._mainForm = new FindForm();
this._mainForm.RichTextBox = this._host.RichTextBox;
this._mainForm.Owner = this._host.MainForm;
this._mainForm.Show();
}
}
}
|
RunメソッドでFindFormを表示しているだけで、特に問題はないでしょう。(表示する前にRichTextBoxの設定と、オーナーウィンドウの設定を行っています。)
メインアプリケーションの作成 †
ようやくここまでたどり着きました。いよいよプラグインを使用するホストのアプリケーションを作成します。
ホストアプリケーションは、Windowsアプリケーションプロジェクトとして作成し(名前は、"MainApplication"とします)、"Plugin.dll"を参照に追加します。
フォームには、RichTextBoxと、メニュー、さらにメッセージを表示するためのStatusBarコントロールを配置します。変更するフォームのプロパティと、フォームに配置するコントロールとそのプロパティ(そしてイベント)の一覧を以下に示します。
コントロール: Form
Name: Form1
Menu: mainMenu
Loadイベント: Form1_Load
コントロール: RichTextBox
Name: mainRichTextBox
Dock: Fill
コントロール: StatusBar
Name: mainStatusbar
コントロール: MainMenu
Name: mainMenu
コントロール: MenuItem
Name: menuPlugins
Text: プラグイン(&P)
コントロール: MenuItem
Name: menuHelp
Text: ヘルプ(&H)
コントロール: MenuItem
Name: menuAbout
Text: バージョン情報(&A)...
Clickイベント: menuAbout_Click
次に前号で作成したPluginInfoクラスをプロジェクトに追加します。ただし、CreateInstanceメソッドでIPluginHostオブジェクトをIPluginHost.Hostプロパティに設定するように変更しています。
PluginInfoクラスは次のようなコードです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
| | Imports System
Public Class PluginInfo
Private _location As String
Private _className As String
Private Sub New(ByVal path As String, ByVal cls As String)
Me._location = path
Me._className = cls
End Sub
Public ReadOnly Property Location() As String
Get
Return _location
End Get
End Property
Public ReadOnly Property ClassName() As String
Get
Return _className
End Get
End Property
Public Shared Function FindPlugins() As PluginInfo()
Dim plugins As New System.Collections.ArrayList
Dim ipluginName As String = _
GetType(Plugin.IPlugin).FullName
Dim folder As String = _
System.IO.Path.GetDirectoryName( _
System.Reflection.Assembly. _
GetExecutingAssembly().Location)
folder += "\plugins"
If Not System.IO.Directory.Exists(folder) Then
Throw New ApplicationException( _
"プラグインフォルダ""" + folder + _
"""が見つかりませんでした。")
End If
Dim dlls As String() = _
System.IO.Directory.GetFiles(folder, "*.dll")
Dim dll As String
For Each dll In dlls
Try
Dim asm As System.Reflection.Assembly = _
System.Reflection.Assembly.LoadFrom(dll)
Dim t As Type
For Each t In asm.GetTypes()
If t.IsClass And t.IsPublic And _
Not t.IsAbstract And _
Not (t.GetInterface(ipluginName) Is Nothing _
) Then
plugins.Add(New PluginInfo(dll, t.FullName))
End If
Next t
Catch
End Try
Next dll
Return CType(plugins.ToArray( _
GetType(PluginInfo)), PluginInfo())
End Function
Public Function CreateInstance( _
ByVal host As Plugin.IPluginHost) As Plugin.IPlugin
Try
Dim asm As System.Reflection.Assembly = _
System.Reflection.Assembly.LoadFrom(Me.Location)
Dim plugin As Plugin.IPlugin = _
CType(asm.CreateInstance(Me.ClassName), _
Plugin.IPlugin)
plugin.Host = host
Return plugin
Catch
End Try
End Function
End Class
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
| | using System;
namespace MainApplication
{
public class PluginInfo
{
private string _location;
private string _className;
private PluginInfo(string path, string cls)
{
this._location = path;
this._className = cls;
}
public string Location
{
get {return _location;}
}
public string ClassName
{
get {return _className;}
}
public static PluginInfo[] FindPlugins()
{
System.Collections.ArrayList plugins =
new System.Collections.ArrayList();
string ipluginName = typeof(Plugin.IPlugin).FullName;
string folder = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly
.GetExecutingAssembly().Location);
folder += "\\plugins";
if (!System.IO.Directory.Exists(folder))
throw new ApplicationException(
"プラグインフォルダ\"" + folder +
"\"が見つかりませんでした。");
string[] dlls =
System.IO.Directory.GetFiles(folder, "*.dll");
foreach (string dll in dlls)
{
try
{
System.Reflection.Assembly asm =
System.Reflection.Assembly.LoadFrom(dll);
foreach (Type t in asm.GetTypes())
{
if (t.IsClass && t.IsPublic && !t.IsAbstract &&
t.GetInterface(ipluginName) != null)
{
plugins.Add(
new PluginInfo(dll, t.FullName));
}
}
}
catch
{
}
}
return (PluginInfo[]) plugins.ToArray(typeof(PluginInfo));
}
public Plugin.IPlugin CreateInstance(Plugin.IPluginHost host)
{
try
{
System.Reflection.Assembly asm =
System.Reflection.Assembly.LoadFrom(this.Location);
Plugin.IPlugin plugin =
(Plugin.IPlugin) asm.CreateInstance(this.ClassName);
plugin.Host = host;
return plugin;
}
catch
{
return null;
}
}
}
}
|
IPluginHostインターフェイスは、フォームクラスで実装します。また、プラグインの読み込みと、メニューへの表示はフォームのLoadイベントハンドラで行い、メニューを選択することにより、プラグインを実行できるようにします。
以下に変更を加えたフォームクラスの主要部分のコード(Windowsフォームデザイナが作成したコードを除く)を示します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
| | Public Class Form1
Inherits System.Windows.Forms.Form
Implements Plugin.IPluginHost
Dim plugins() As Plugin.IPlugin
Public ReadOnly Property MainForm() As Form _
Implements Plugin.IPluginHost.MainForm
Get
Return Me
End Get
End Property
Public ReadOnly Property RichTextBox() As RichTextBox _
Implements Plugin.IPluginHost.RichTextBox
Get
Return mainRichTextBox
End Get
End Property
Public Sub ShowMessage(ByVal plugin As Plugin.IPlugin, _
ByVal msg As String) _
Implements Plugin.IPluginHost.ShowMessage
mainStatusbar.Text = msg
End Sub
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Dim pis As PluginInfo() = PluginInfo.FindPlugins()
Me.plugins = New Plugin.IPlugin(pis.Length - 1) {}
Dim i As Integer
For i = 0 To (Me.plugins.Length) - 1
Me.plugins(i) = pis(i).CreateInstance(Me)
Next i
Dim plugin As Plugin.IPlugin
For Each plugin In Me.plugins
Dim mi As New MenuItem(plugin.Name, _
AddressOf menuPlugin_Click)
Me.menuPlugins.MenuItems.Add(mi)
Next plugin
End Sub
Private Sub menuPlugin_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles menuPlugins.Click
Dim mi As MenuItem = CType(sender, MenuItem)
Dim plugin As Plugin.IPlugin
For Each plugin In Me.plugins
If mi.Text = plugin.Name Then
plugin.Run()
Return
End If
Next plugin
End Sub
Private Sub menuAbout_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles menuAbout.Click
Dim msg As String = "インストールされているプラグイン" + vbLf _
+ "(名前 : 説明 : バージョン)" + vbLf + vbLf
Dim plugin As Plugin.IPlugin
For Each plugin In Me.plugins
msg += String.Format("{0} : {1} : {2}" + vbLf, _
plugin.Name, plugin.Description, plugin.Version)
Next plugin
MessageBox.Show(msg)
End Sub
End Class
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
| | namespace MainApplication
{
public class Form1 : System.Windows.Forms.Form, Plugin.IPluginHost
{
Plugin.IPlugin[] plugins;
public Form MainForm
{
get
{
return (Form) this;
}
}
public RichTextBox RichTextBox
{
get
{
return mainRichTextBox;
}
}
public void ShowMessage(Plugin.IPlugin plugin, string msg)
{
mainStatusbar.Text = msg;
}
private void Form1_Load(object sender, System.EventArgs e)
{
PluginInfo[] pis = PluginInfo.FindPlugins();
this.plugins = new Plugin.IPlugin[pis.Length];
for (int i = 0; i < this.plugins.Length; i++)
this.plugins[i] = pis[i].CreateInstance(this);
foreach (Plugin.IPlugin plugin in this.plugins)
{
MenuItem mi = new MenuItem(plugin.Name,
new EventHandler(menuPlugin_Click));
this.menuPlugins.MenuItems.Add(mi);
}
}
private void menuPlugin_Click(
object sender, System.EventArgs e)
{
MenuItem mi = (MenuItem) sender;
foreach (Plugin.IPlugin plugin in this.plugins)
{
if (mi.Text == plugin.Name)
{
plugin.Run();
return;
}
}
}
private void menuAbout_Click(
object sender, System.EventArgs e)
{
string msg = "インストールされているプラグイン\n"
+ "(名前 : 説明 : バージョン)\n\n";
foreach (Plugin.IPlugin plugin in this.plugins)
{
msg += string.Format("{0} : {1} : {2}\n",
plugin.Name, plugin.Description, plugin.Version);
}
MessageBox.Show(msg);
}
}
}
|
このメインアプリケーションを実行させるには、実行ファイルのあるフォルダに"plugins"というフォルダを作り、そこに前に作成したプラグイン"CountChars.dll"と"FindString.dll"をコピーしてください。うまくいくと、「プラグイン」メニューに「文字数取得」と「文字列の検索」が追加され、プラグインの機能を呼び出すことができるようになります。
以上でプラグイン機能を実現させる方法に関する解説はおしまいです。ここで紹介した知識を応用することにより、より複雑なプラグインも作成できるでしょう。この記事を読んで、プラグインを使ったアプリケーションを作ってみようと思われる方が一人でもいらっしゃるならばうれしいのですが。
コメント †