メインコンテンツまでスキップ

拡張機能の開発

はじめに

本文書はC#を知っていてLightning Review(以下、LR)の拡張機能を開発したい方のために必要な開発の手順を記したものです。
本文書に沿って作成したサンプルコードであるチュートリアルエクステンションも一緒に参照していただけると、より開発しやすくなると思います。

準備

Visual Studio 2019またはVisual Studio 2022をインストールしてください。
また、こちらから.NET Framework 4.6.2 Developer Packをインストールしてください。
VisualStusioでクラスライブラリの新規プロジェクトを作成します。ダイアログなどコントロールの追加を伴う拡張機能を作成する際はWPF関連の参照を持つWPFユーザーコントロールライブラリの新規プロジェクトを作成してください。フレームワークは.NET Framewwork 4.6.2を選択してください。
WPF:デスクトップアプリケーションを開発するためのUIフレームワークです。LRはWPFで開発しています。

Visual Studio のプロジェクトテンプレートをインストールする事で、簡単に拡張機能のプロジェクトを新規作成できます。詳細は以下のリンク先を参照ください。

上記のテンプレートを利用することを推奨しますが、それを利用しなくても拡張機能のプロジェクトは作成可能です。以下にその手順を記します。

アセンブリ名が他の拡張機能と重複すると拡張機能の読み込みに失敗してしまうので、ユニークなアセンブリ名を付けて下さい。アセンブリ名はプロジェクトのプロパティのアプリケーションタブから変更することができます。

LightningReview.ExtensionFrameworkというNugetパッケージをインストールし、参照します。
プロジェクトの[参照]を右クリックして、[Nugetパッケージの管理]メニューをクリックします。
LightningReview.ExtensionFrameworkを選択し、最新版をインストールしてください。

拡張機能の実装

Extensionクラスから派生したクラスを実装する

ExtensionクラスとはLRの起動時にLRに拡張機能を読み込むためのクラスです。このクラスを派生させて拡張機能の名前やIDの設定、メニューの挿入などのLR起動時に行いたい処理を実装できます。(例: TutorialExtension )。 クラスにExtensionExport 属性を指定をしてください。最初のパラメータのId(コード例のDensoCreate.Tutorial )は拡張機能をユニークに認識するキー文字列になりますので必ず指定します。Idは他の拡張機能と重複してはいけません。またアルファベット、ハイフン、アンダースコア、ドットからなる文字列となります。このIdは C:\Users\ユーザー名\AppData\Local\DENSO CREATE\Lightning Review 直下に保存される各拡張機能の設定ファイルのファイル名になりますのであまり長い名前は良くありません。 英語でYourCompanyName.YourSimpleExtensionName のような形式、長くても20-30文字程度の長さで付けると良いです。例えば DensoCreate.CopyPasteDensoCreate.JiraInteg のような形です。2つ目は日本語名、3つ目は英語名になります。これらは[拡張機能の管理]ダイアログの拡張機能の一覧で表示される文字列になります。

メニューを追加する

Extension クラスから派生したクラスの中でOnActivateメソッドをオーバーライドし、RegisterMenuメソッドを実装するとメニューを登録できます。OnActivateメソッドはLRの起動時に実行されます。メニューの挿入対象のウインドウやコントロールをLocationメソッドで指定できます( ParentBefore,After,Top,Bottomで相対位置を指定できます)。Commandメソッドでメニューをクリックしたときに実行する処理を指定できます。以降で説明するコマンドクラスをCommand<AddIssuesCommand>()のように<>内に指定してください。そして、最後にBuildメソッドを呼ぶことでメニューを追加できます。

using System.Linq;
using System.Windows;
using LightningReview.ExtensionFramework;
using DensoCreate.TutorialExtension.Commands;

namespace DensoCreate.TutorialExtension
{
[ExtensionExport("DensoCreate.Tutorial", "チュートリアルエクステンション","Tutorial Extension")]
public class TutorialExtension : Extension
{
protected override void OnActivate()
{
// メインメニューの [ツール] - [プロパティの表示順を変更] の1つ上(Before)にメニューを作成する例
RegisterMenu()
.Location("ReviewWindow/MainMenu")
.Parent("ツール")
.Before("プロパティの表示順を変更")
.Command<AddIssuesCommand>()
.Build();
}
}
}


ツールバーにボタンを追加する

メニュー以外にもツールバーにボタンを追加することができます。メニューの追加と同様にExtension クラスから派生したクラスの中でOnActivateメソッドをオーバーライドして実装します。RegisterToolBarItemメソッドでツールバーへアイテムを追加でき、SetButtonメソッドでButton型のアイテムを挿入できます。Beforeメソッド,Afterメソッドでボタン挿入位置の相対位置を指定できます。また、SetTextStyleメソッド、SetImageStyleメソッド、SetImageAndTextStyleメソッドでボタンの見た目を「テキストのみ」、「画像のみ」、「画像とアイコンの両方」のいずれかに切り替えることができます。

namespace DensoCreate.TutorialExtension
{
[ExtensionExport("DensoCreate.Tutorial", "チュートリアルエクステンション","Tutorial Extension")]
public class TutorialExtension : Extension
{
protected override void OnActivate()
{
// ツールバーのピポット分析ボタンの後(After)にメニューを作成する例
// SetButtonでボタンを配置できる。SetTextでテキスト形式のボタンを配置できる。
RegisterToolBarItem()
.Location("ReviewWindow/ToolBar")
.After("ピボット分析")
.SetButton()
.SetTextStyle()
.Command<MessageSettingCommand>()
.Build();
}
}
}

利用可能なメニューのロケーション一覧は以下の通りです。

  • レビューウィンドウ
    • メインメニュー:ReviewWindow/MainMenu
    • タイルビューのコンテキストメニュー:ReviewWindow/IssueTileViewControl/IssueListViewContextMenu
    • グリッドビューのコンテキストメニュー:ReviewWindow/IssueGridViewControl/IssueGridViewContextMenu
    • 詳細ビューの指摘一覧のコンテキストメニュー:ReviewWindow/IssueDetailViewControl/IssueDetailListViewContextMenu
    • アウトラインツリーのコンテキストメニュー:ReviewWindow/DocumentTreeNavigator/TreeViewContextMenu
    • ツールバー:ReviewWindow/ToolBar
  • レビューエクスプローラー
    • フォルダ一覧のコンテキストメニュー:ReviewExplorer/FolderListViewContextMenu
    • グリッドのコンテキストメニュー:ReviewExplorer/ReviewDataGridContextMenu
    • ツールバー:ReviewExplorer/ToolBar

メニューで実行される処理を実装する

WPFはメニュー等、UI操作から実行したい処理の設定や管理をするためにICommandというインターフェースを提供しています。ExtensionCommand クラスは拡張機能用にICommandを実装し、ラッピングしたクラスです。このクラスから派生したコマンドクラスを実装することで、メニューの名前やメニュー押下時に実行したい処理などを実装することができます。コマンドの実行と実行可否はOnExecuteメソッドとOnCanExecuteメソッドをオーバーライドします(Excecuteメソッド,CanExecuteメソッドはベースクラスで隠蔽されています)。 OnExecuteメソッド内の処理は上記で追加したメニューを押したときに実行されます。OnCanExecuteメソッドではコマンドの有効無効を切り替えることができます。

using System;
using System.Linq;
using System.Windows.Input;
using LightningReview.ExtensionFramework;
using DensoCreate.TutorialExtension.Model;

namespace DensoCreate.TutorialExtension.Commands
{
public class AddIssuesCommand : ExtensionCommand
{
public AddIssuesCommand()
{
// メニュー名
Title = "指摘の追加(_U)";

// ショートカットを指定する場合はこのようにします(Ctrl+D)
Key = Key.D;
Modifiers = ModifierKeys.Control;
}

protected override void OnExecute(object parameter = null)
{
// アクティブなレビューウィンドウを取得
var reviewWindow = App.ActiveReviewWindow;

...
}

protected override bool OnCanExecute(object parameter = null)
{
if ( ... )
{
// コマンドが有効
return true;
}
else
{
// コマンドが無効
return false;
}
}
}
}

メニューにアイコンを設定する

メニューのアイコンは、次のようにコマンドで行います。

    class AddIssuesCommand : ExtensionCommand
{
public AddIssuesCommand()
{
// Properties/Resouces.resxに登録されているアイコンリソース名を指定することで
// アイコンが表示できます。
// ここでは、Properties/Resources.resxにAddIssuesIconというイメージが登録されているとします。
IconResourceName = "AddIssuesIcon"

// ...
}
}

1回のUndo操作でまとめて元に戻す処理を実装する

BeginEditメソッドで囲んだ範囲は、1つの編集単位となり、1回のUndo操作で複数の編集操作を元に戻すことができます。

    class AddIssuesCommand : ExtensionCommand
{
public AddIssuesCommand()
{
...
}

protected override void OnExecute(object parameter = null)
{
var reviewWindow = App.ActiveReviewWindow;

// BeginEdit()で囲んだ範囲の編集操作を1つの編集単位とする
using (reviewWindow.BeginEdit())
{
...
}
}
}
}

LRのオブジェクトを操作する

LRのドキュメントはIDocument、アウトラインノードはIOutlineNode、指摘はIIssue というオブジェクトで操作することができます。


class AddIssuesCommand : ExtensionCommand
{
public AddIssuesCommand()
{
...
}


/// <summary>
/// コマンドの実行
/// </summary>
/// <param name="parameter"></param>
protected override void OnExecute(object? parameter = null)
{
// アクティブなレビューウィンドウを取得
var reviewWindow = App.ActiveReviewWindow;

// 次のようにSettingオブジェクトを経由して永続化したメッセージを取得できる。
var settings = Extension.Settings.GetValue<TutorialSettings>("tutorialSettings");

// 永続化情報が無ければ初期化
if (settings == null)
{
settings = new TutorialSettings();
}

// 指摘内容の文字列を作成
var description = $"{settings.Message}{Environment.NewLine}{settings.Date?.ToString("yyyy/MM/dd")}";

// BeginEdit()で囲んだ範囲の編集操作を1つの編集単位とする。
using (reviewWindow.BeginEdit())
{
// レビューウィンドウにドキュメントを追加
IDocument document = reviewWindow.Review.AddDocument();

// ドキュメントに"ノード"という名前のアウトラインノードを追加
IOutlineNode outlineNode = document.OutlineTree.AddChild("ノード");

// アウトラインノードに指摘を追加
IIssue issue1 = outlineNode.AddIssue();

// 指摘内容にメッセージと日付を追加
issue1.Description = description;

// 2つ目の指摘を追加
IIssue issue2 = outlineNode.AddIssue();
issue2.Description = description;

// 同じ指摘だったら(GIDが同じだったら)
if (issue1.Equals(issue2))
{
//....
}
}
}
}

LRで発生するイベントをトリガーにして処理を実行させる

LRではレビューファイルの保存前後、LRの起動後、LRの終了前や指摘が編集された時など様々なイベントを公開しています。イベントはExtensionクラスまたはExtensionCommandクラスのAppプロパティから参照することができます。以下はExtensionクラスの派生クラスで保存後のイベント(ReviewAfterSaveイベント)にメッセージボックスが表示されるイベントハンドラ(AppOnReviewAfterSaveメソッド)を登録する例です。


namespace DensoCreate.TutorialExtension
{
[ExtensionExport("DensoCreate.Tutorial", "チュートリアルエクステンション","Tutorial Extension")]
public class TutorialExtension : Extension
{
protected override void OnActivate()
{
...


// 保存後イベントにイベントハンドラを登録する
// 保存が完了すると、メッセージボックスが出る
App.ReviewAfterSave += AppOnReviewAfterSave;
}

/// <summary>
/// レビューファイル保存後にメッセージボックスを出すイベントハンドラ
/// </summary>
/// <param name="arg1"></param>
/// <param name="arg2"></param>
private void AppOnReviewAfterSave(object arg1, ReviewEventArgs arg2)
{
// ドキュメントの数と指摘の数を取得
var documentCount = arg2.ReviewWindow.Review.Documents.Count();
var issueCount = arg2.ReviewWindow.Review.GetAllIssues().Count();

var saveMassage = $"ドキュメントが{documentCount}件、 指摘は{issueCount}件です!";
MessageBox.Show(saveMassage, "Lightning Review", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
}

拡張機能の設定値を保存・復元する

拡張機能の設定値はJSON形式で保存・復元することができます。保存・復元にはExtensionクラスのSettingsプロパティを用います。SettingsプロパティはExtensionCommandクラスの派生クラスやExtensionクラスの派生クラスからアクセスできます。コマンドクラスの場合はExtension プロパティからアクセスできます。
オブジェクトをSettingsプロパティで保存・復元するには、Newtonsoft.jsonというNuGetパッケージをインストールし、JSON形式で扱えるオブジェクトを作成する必要があります。プロジェクトの[参照]を右クリックして、[Nugetパッケージの管理]メニューをクリックします。バージョンを12.0.3にしてインストールしてください。Lightning Review本体のNewtonsoft.jsonのバージョンが12.0.3であるため、異なるバージョンをインストールすると拡張機能を読み込めなくなります。

Newtonsoft.Jsonのインストールができたら、保存・復元したい設定値を定義したプロパティがあるクラスを作成します。保存したいプロパティにJsonProperty属性を付けることでJSON形式で保存することができるようになります。

using Newtonsoft.Json;

namespace DensoCreate.TutorialExtension.Model
{
/// <summary>
/// 本拡張機能におけるチュートリアル用の設定値を保持する
/// </summary>
public class TutorialSettings
{
/// <summary>
/// メッセージ
/// </summary>
[JsonProperty("message")]
public string Message { get; set; } = "Hello";
}
}


上記オブジェクトは、次のように設定を取得したり更新できます。 SetValueメソッドの引数に保存したいデータのキーとオブジェクトを設定すると、JSON形式のファイルに保存することができます。 GetValueメソッドはJSON形式で保存したデータからキーと一致するデータを指定した型に復元することができます。以下の例でいうと、tutorialSettingsというキーで保存されているデータをTutorialSettingsというオブジェクトに復元できます。指定した型にJSON形式の文字列を復元します。

    public class MessageSettingCommand : ExtensionCommand
{
...

protected override void OnExecute(object parameter = null)
{
// 次のようにSettingオブジェクトを経由して永続化したメッセージを取得できる
var tutorialSettings = Extension.Settings.GetValue<TutorialSettings>("tutorialSettings");

// 永続化情報が無ければ初期化
if (tutorialSettings == null)
{
tutorialSettings = new TutorialSettings();
}

...

// 設定値を保存
Extension.Settings.SetValue("tutorialSettings", tutorialSettings);

}
}
}

以下のような設定ファイルが生成されます。


{
"tutorialSettings": {
"messgae": "Hello"
},
}

設定ファイルは C:\Users\ユーザー名\AppData\Local\DENSO CREATE\Lightning Review直下に extension.<extensionId>.jsonというファイルで拡張機能ごとに保存されます(extensionIdはExtensionクラスに属性として設定した第1引数のことです)。

    [ExtensionExport("DensoCreate.Tutorial", "チュートリアルエクステンション","Tutorial Extension")]
public class TutorialExtension : Extension
{
protected override void OnActivate()
{
...
}
}

上記の拡張機能の設定は extension.DensoCreate.Tutorial.jsonというファイルになります。

設定ファイルはLRの起動時(厳密には拡張機能のOnActivate メソッド直前)にロードし、LRの終了時( OnDeactivateメソッド実行の直後)に作成・更新されます。設定ファイルはエントリが無ければ作成されません。1つでもエントリが設定(Settings.SetValueが実行)されると保存されるようになります。

ダイアログの見た目をLRのテーマに合わせる

ダイアログの背景色と文字色は、LRのテーマ色に合わせる必要があります。WindowクラスのSetThemeColorメソッドをコンストラクタで呼び出すことで、そのダイアログの背景色と文字色をテーマ色に設定します。

    public partial class NotificationChannelSettingDialog : Window
{
public NotificationChannelSettingDialog()
{
InitializeComponent();

// ダイアログの背景色と文字色をテーマ色に合わせる
this.SetThemeColor();
}
}

日付選択コントロール

日付を選択するコントロールとしてWPFにはDatePickerやCalenderがありますが、それらを使用した場合コントロールの色がLRのテーマ色と乖離して見づらい表示になってしまいます。以下の手順に従ってDateTimePickerというコントロールをxamlで配置できます。

  1. DateTimePickerを使用したい箇所で例のようにclr名前空間を追加してください。
    例:xmlns:extensionFramework="clr-namespace:LightningReview.ExtensionFramework.Framework.Controls;assembly=LightningReview.ExtensionFramework"
  2. <1で指定した名前空間:DateTimePicker>のようにしてコントロールを配置できます。
    例:<extensionFramework:DateTimePicker/>

DateTimePickerの基本的な使い方としては、SelectedDateTimeプロパティで選択した日付の取得または設定をします。また、NullValueTextプロパティで日付が未選択状態のときのコントロールに表示したい文字列を設定できます。

拡張機能のビルドとデバッグ

  • ビルドします。
  • 作成されたDLL(プロジェクトフォルダ\bin\Debugにあります。)を C:\Users\ユーザー名\AppData\Local\DENSO CREATE\Lightning Review\extensions\TutorialExtensionのように任意の名前のフォルダを作成し、その下にコピーします。(LightningReview.ExtensionFramework.dll や newtonsoft.json.dllのようなLRでも参照しているファイルは配置不要)
  • LRを実行すると実行フォルダの extensionsフォルダ、および上記の C:\Users\ユーザー名\AppData\Local\DENSO CREATE\Lightning Review\extensions\extensionsフォルダの拡張機能をアクティベートします。
  • デバッグ時は、あらかじめLRを立ち上げておき、[デバッグ]-[プロセスにアタッチ]メニューをクリックして使用可能なプロセスからLightning Reviewを選択しアタッチすればブレークやステップ実行なども可能です。

デバッグが楽になるのでやっておくとよい設定

  • プロジェクトを右クリックして[オプション]-[ビルドイベント]を選択します。
  • ビルド後イベントのコマンドラインに次のように設定すると、%AppData%\Local\DENSO CREATE\Lightning Review\extensions\に自動的にフォルダを作成し、作成されたDLLがコピーされます。(Visual Studio のプロジェクトテンプレートを利用していれば設定済みです)
set DESTINATION_FOLDER=%USERPROFILE%\AppData\Local\DENSO CREATE\Lightning Review\extensions\$(ProjectName)
rd /s /q "%DESTINATION_FOLDER%"
xcopy /S /I /Q /Y "$(TargetDir)*" "%DESTINATION_FOLDER%"
  • [オプション]-[デバッグ]を選択し、外部プログラムの開始にチェックを入れ、C:\Program Files (x86)\Denso Create\Lightning Review\LightningReview.exeを参照させます。
  • これをやっておくと、プロジェクトをビルドして実行するだけでデバッグできます。
  • 本設定をした場合LRが別で立ち上がっている状態でビルドすると、ビルド後イベントで指定したコマンドでエラーが発生します。LRは全て閉じた状態でビルドしてください。

チュートリアル用の拡張機能

上記手順で実装したチュートリアル用の拡張機能のソースコード全体は、以下となります。ご利用ください。
チュートリアルエクステンション

API情報

拡張機能の開発に利用できるAPIは、インターフェイスで定義しています。
レビュー、ドキュメント、アウトライン、指摘に対して、取得、追加、変更、削除などができます。
保存の実行時のイベントハンドラを登録することなども可能です。
利用可能なAPIの一覧は、以下となります。ご利用ください。
ExtensionFremeworkのリファレンス


応用編

ツールバーにトグルボタンを追加する

RegisterToolBarItemメソッドでツールバーへアイテムを追加するところまでは「ツールバーにボタンを追加する」の章と同様です。SetButtonメソッドではなく、SetToggleButtonメソッドを指定することでToggleButton型のアイテムを追加できます。

namespace DensoCreate.TutorialExtension
{
[ExtensionExport("DensoCreate.Tutorial", "チュートリアルエクステンション","Tutorial Extension")]
public class TutorialExtension : Extension
{
protected override void OnActivate()
{
// ツールバーのピポット分析ボタンの後(After)に、メニューを作成する例
// SetToggleButtonでトグルボタンを配置できる。SetImageStyleでイメージで表現するボタンを配置できる。
RegisterToolBarItem()
.Location("ReviewWindow/ToolBar")
.After("ピボット分析")
.WithSeparatorBefore()
.SetToggleButton()
.SetImageStyle()
.Command<EnableMessageSettingCommand>()
.Build();
}
}
}

トグルボタンを追加した場合、ExtensionCommandクラスのOnExecuteメソッドの引数でボタンをクリックした後のトグルボタンのチェック状態(ToggleButton.IsChecked)を渡します。 OnExecuteメソッドの引数をbool型にキャストして、トグルボタンのチェック状態を取得してください。OnExecuteメソッドの引数がtrueであれば、トグルボタンを押したことによってトグルボタンがチェック状態になったことを意味します。 OnExecuteメソッドの引数がfalseであれば、トグルボタンを押したことによってトグルボタンがチェック状態でなくなったことを意味します。

namespace DensoCreate.TutorialExtension.Commands
{
/// <summary>
/// メッセージの設定可否を切り替えるコマンド
/// </summary>
public class EnableMessageSettingCommand : ExtensionCommand
{
#region プロパティ

/// <summary>
/// 対象の拡張機能
/// </summary>
public TutorialExtension TargetExtension => (TutorialExtension)Extension;

#endregion

#region 公開サービス

/// <summary>
/// コマンドの実行
/// </summary>
/// <param name="parameter">
/// メッセージの設定可否をbool値で表現した値
/// true:可
/// false:否
/// </param>
protected override void OnExecute(object parameter = null)
{
if (parameter == null) return;

// bool値の場合は、メッセージの設定可否を切り替える
if (parameter is bool boolValue)
{
TargetExtension.MessageSettingEnabled = boolValue;
}
}

#endregion
}
}

拡張機能の設定値を保存・復元する

拡張機能の設定の保存/復元は、ExtensionクラスのSettingsプロパティを用います。上記の拡張機能の設定値を保存・復元するで解説した永続化に対応したJSONのPOCOオブジェクトを作成する方法ではなく、以下のように実装することもできます。設定ファイルのキーをパラメータにします。

// 保存した設定値を取得します。
var myKey1 = Extension.Settings.GetValue<string>("myKey1");
var myKey2 = Extension.Settings.GetValue<int>("myKey2");
var myKey3 = Extension.Settings.GetValue<string[]>("myKey3");

// 設定が無い場合に指定したデフォルト値を取得する場合は次のようにします。
var myKey1 = Extension.Settings.GetValue<string>("myKey1","myDeaultValue");

// 保存するための設定は次のようにします。
Extension.Settings.SetValue("myKey1", "myKey1 value");
Extension.Settings.SetValue("myKey2", 30);
Extension.Settings.SetValue("myKey2", new string[] { "aaa", "bbb", "ccc" });

上記の例を実行すると、次のように保存されます。

{
"myKey1": "myKey1 value",
"myKey2": 30,
"myKey3": [
"aaa",
"bbb",
"ccc"
]
}

拡張機能の例外

拡張機能での例外は UserExceptionクラスを送出すると、ユーザー向けのエラーとしてMessageBoxを表示します。それ以外の例外は内部エラーとして判断され、システムエラーダイアログを表示します。そのため、ユーザー向けのエラーメッセージに例外を用いる場合は、UserExceptionで送出するようにして下さい。

MVVMをサポートするクラス

コマンドからダイアログを表示する場合は、MVVMをサポートするクラスがあります。ViewModelBaseDelegeteCommand を利用すると便利です。

using LightningReview.ExtensionFramework;

// 一般的なビューモデルの実装
public class MyViewModel : ViewModelBase
{
private string m_MyProp;

// Viewからバインドされるプロパティ
public string MyProp {
get=> m_MyProp;
// SetPropertyを用いることでViewに変更通知を発行できます
set=> SetProperty(ref m_MyProp,value);
}

// コマンドの定義
public DelegateCommand AddCommand => new DelegateCommand( ()=>{
// コマンドで実行する処理を記述します
}, ()=>{
// コマンドが実行可能か判定する処理を記述します
return true;
});
}

ドキュメント解析(IDocumentParser)の開発

  • アウトライン解析(特定の拡張子のファイルに対してアウトラインノードを自動で作成する機能)の拡張機能を追加する場合は、DocumentParserクラスを派生したパーサクラスを作成します。コンストラクタでAddFileExtensionを用いて対象の拡張子を指定しておきます。
  • Parseメソッドを実装してアウトラインを作成します。Jumpメソッドをオーバーライドすると、指定箇所にジャンプします。既定の動作ではProcess.Start()を用いています。
    public class MarkdownDocumentParser : DocumentParser
{
public MarkdownDocumentParser()
{
// 対象となる拡張子を登録します(複数登録可能)
AddFileExtension(".md");
}

// [ドキュメントからアウトラインを作成]メニューの実行時に呼ばれるメソッドです。
// ここに、ファイルの読み込みやアウトラインの作成を行う処理を実装します。
public override bool Parse(IDocument document, string filePath = "")
{
var fileText = File.ReadAllText(filePath);

foreach ( ...)
{
...
}
}
}
  • ExtensionクラスのOnActivateRegisterDocumentParserで登録します。
namespace DensoCreate.SampleExtension
{
[ExtensionExport("サンプル拡張機能")]
class SampleExtension : Extension
{
protected override void OnActivate()
{
//...

// パーサの登録
RegisterDocumentParser<MarkdownDocumentParser>();
}
}
}

レビューファイルのデータを収集・更新する

レビューファイルのデータを収集・更新するにはIAppインターフェースが持つGetReviewFileServiceメソッドを使用し、IReviewFileService型のオブジェクトを取得することで実現できます。
IReviewFileServiceインターフェースではレビューファイルの新規作成、開く、保存、閉じるを行うことができます。
新規作成または、開くを実行すると、IReview型のオブジェクトを取得できます。IReview型のオブジェクトから「LRのオブジェクトを操作する」の章で説明した通り、ドキュメント、アウトラインや指摘などのレビューの編集をすることができます。

// 更新対象のレビューファイルを読み込む
IReviewFileService reviewFileService = App.GetReviewFileService();
IReview review = reviewFileService.OpenReview(@"C:\XXX\YYY.revx");

try
{
// レビューファイルを編集
IDocument document = review.AddDocument();
document.AddIssue();

// レビューファイルを保存
reviewFileService.SaveReview(@"C:\XXX\YYY.revx", review);
}
finally
{
// レビューファイルを閉じる
reviewFileService.CloseReview(review);
}

レビューファイルにメタデータを追加する

レビューが持つオブジェクトにSetMetaDataメソッドでKeyとValueを指定して新しいデータを持たせて保存することができます。
持たせたデータを使用したい場合は、GetMetaData<T>メソッドに復元したいデータの型とKeyを指定します。また、追加するデータを暗号化することもできます。

// レビューにドキュメントを追加する
IDocument document = App.ActiveReviewWindow.Review.AddDocument();

// 追加したドキュメントにKeyが"testKey"、Valueが"testValue"のメタデータを設定する。
// 3つ目の引数でtrueを指定するとValueを暗号化できる。
// 暗号化はstring型のValueのみに適用される。
document.SetMetaData("testKey", "testValue", true);

// Keyが"testKey"のメタデータを取得する。
// 2つ目の引数は値が復元できなかった場合のデフォルト値を設定できる。
// 3つ目の引数はtrueを指定するとことで、暗号化したデータを複合できる。
IMetaData metaData = document.GetMetaData<string>("testKey", "defaultValue", true);