UiPath Activity Creatorを使ってみる。（その２：簡単なアクティビティ作成とプロパティの設計・設定について）


#このドキュメントの概要

　[前回](https://qiita.com/SuetakeYoichi/items/2bbd7affbbcf32e002c1) はUiPath Activity Creatorの導入を中心に説明を行いました。

　今回は実際にUiPath Activity Creatorを使って簡単なカスタムアクティビティを作成してみます。またアクティビティの入出力を担うプロパティの設定について、代表的な記述の仕方を説明します。

#サンプルアクティビティの仕様とその作り方
　UiPathのサイト上でのサンプルでもつかわれている、足し算カスタムアクティビティを作ってみます。仕様としてはInt32型の入力値a,bを加算し、Int32型の値cを出力します。

まずWizardを起動して、Add Activityします。
![uac2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/eff2f75e-06da-f074-2f8a-e402381b5d69.png)

次に追加するアクティビティの設定を行います。今回はTestSumという名前のアクティビティにしました。
![uac2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/86c0a5b7-7e02-8f04-f565-2f1539e6bd07.png)

次にプロパティを追加します。a,bがInt32型の入力、cがInt32型の出力です。
![uac2-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/1a02cfcc-07b0-5a9c-b4b1-c05c1428ac50.png)

これで準備完了です。Activityの定義画面からFinishをクリックします。コードが自動的に生成されたます。そのコードを見てみましょう。

```TestSum.cs
using System;
using System.Activities;
using System.Threading;
using System.Threading.Tasks;
using Company.Product2.Activities.Properties;
using UiPath.Shared.Activities;
using UiPath.Shared.Activities.Localization;

namespace Company.Product2.Activities
{
    [LocalizedDisplayName(nameof(Resources.TestSum_DisplayName))]
    [LocalizedDescription(nameof(Resources.TestSum_Description))]
    public class TestSum : BaseAsyncCodeActivity
    {
        #region Properties

        [LocalizedDisplayName(nameof(Resources.TestSum_A_DisplayName))]
        [LocalizedDescription(nameof(Resources.TestSum_A_Description))]
        [LocalizedCategory(nameof(Resources.Input_Category))]
        public InArgument<int> A { get; set; }

        [LocalizedDisplayName(nameof(Resources.TestSum_B_DisplayName))]
        [LocalizedDescription(nameof(Resources.TestSum_B_Description))]
        [LocalizedCategory(nameof(Resources.Input_Category))]
        public InArgument<int> B { get; set; }

        [LocalizedDisplayName(nameof(Resources.TestSum_C_DisplayName))]
        [LocalizedDescription(nameof(Resources.TestSum_C_Description))]
        [LocalizedCategory(nameof(Resources.Output_Category))]
        public OutArgument<int> C { get; set; }

        #endregion


        #region Constructors

        public TestSum()
        {
        }

        #endregion


        #region Protected Methods

        protected override void CacheMetadata(CodeActivityMetadata metadata)
        {
            if (A == null) metadata.AddValidationError(string.Format(Resources.ValidationValue_Error, nameof(A)));
            if (B == null) metadata.AddValidationError(string.Format(Resources.ValidationValue_Error, nameof(B)));

            base.CacheMetadata(metadata);
        }

        protected override async Task<Action<AsyncCodeActivityContext>> ExecuteAsync(AsyncCodeActivityContext context, CancellationToken cancellationToken)
        {
            // Inputs
            var a = A.Get(context);
            var b = B.Get(context);

            ///////////////////////////
            // Add execution logic HERE
            ///////////////////////////

            // Outputs
            return (ctx) => {
                C.Set(ctx, null);
            };
        }

        #endregion
    }
}
```

　このままではロジックがないので、加算のロジックを追加します。ExecuteAsyncメソッドについて以下のように加算のロジックと、戻り値の設定を行います。

```
            // Inputs
            var a = A.Get(context);
            var b = B.Get(context);

            ///////////////////////////
            // Add execution logic HERE
            ///////////////////////////
            ///
            var c = a + b;

            // Outputs
            return (ctx) => {
                C.Set(ctx, c);
            };
```
これで実装は完了です。それではBuildしてみましょう。
![uac2-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/0a73eae6-e3f1-7b9d-3b47-743e65e306c3.png)

すでにActivity Creatorに設定がありますので、Build指示するだけで、プロジェクトフォルダ\Output\bin\ReleaseまたはDebug\Package以下にnupkgファイルが出力されます。
![uac2-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/90d341cc-1c0b-202c-b215-9cbd390361ca.png)

このnupkgファイルをUipathのパッケージ管理から参照できる場所に置きます。
パッケージ管理からは下記のように見えますので、これをインストールします。
![uac2-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/b8a41a50-a308-8dd7-e44b-238fb386dfab.png)

インストールが完了すると、アクティビティパネル上で以下のように表示されます。
![uac2-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/a38dd4e1-c061-d217-24e2-553df2a9517a.png)

これをデザインパネルに配置すると以下のようになります。（下図は値が入力された状態です）
![uac2-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/d14e1650-abd5-9cb5-89cd-b24ecc7a19a9.png)

実際に値を入力して、期待する値が表示されるか確認してみましょう。
期待通りの動作が確認できれば完成です。


#プロパティの設計・設定について

今回実際に自動生成されたプロパティに関する箇所を見てみます。

```
        [LocalizedDisplayName(nameof(Resources.TestSum_A_DisplayName))]
        [LocalizedDescription(nameof(Resources.TestSum_A_Description))]
        [LocalizedCategory(nameof(Resources.Input_Category))]
        public InArgument<int> A { get; set; }

        [LocalizedDisplayName(nameof(Resources.TestSum_B_DisplayName))]
        [LocalizedDescription(nameof(Resources.TestSum_B_Description))]
        [LocalizedCategory(nameof(Resources.Input_Category))]
        public InArgument<int> B { get; set; }

        [LocalizedDisplayName(nameof(Resources.TestSum_C_DisplayName))]
        [LocalizedDescription(nameof(Resources.TestSum_C_Description))]
        [LocalizedCategory(nameof(Resources.Output_Category))]
        public OutArgument<int> C { get; set; }
```

今回のプロパティは```InArgument<int>```型または```OutArgument<int>```型として定義されています。
このように定義することにより、UiPathの呼び出し側からワークフロー上の変数等の値を渡すことができるようになります。多くの場合、UiPathの呼び出し側からは変数を渡す必要があるかと思いますので、基本的にはこの型を使用しましょう。ただし値の取得については
```var a = A.Get(context);```
のように記述する必要がありますので、その点は注意が必要です。

　一方で単純にプロパティの型をInt型として定義することもできます。実際に以下のように記述してBuildしてみます。
```public int D {get; set;}```


このように記述した場合もプロパティは生成されます。以下Dというプロパティが追加されました。
![uac2-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/8a9475dc-da74-f70b-e93e-d93e226a51d1.png)

しかしそこには定義した型のリテラル値しか入力することができません。int32で定義された変数iを入力しても下記のようにエラーとなります。
![uac2-A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/b76878fd-ddf0-ad96-3b7a-a9a0ef51758f.png)

　このようなケースは使い道がないようにも思えますが、その項目によっては、よりユーザビリティが高いUIが用意されています。
　具体的には、例えばbool型を指定するとその項目はチェックボックスとして表示されます。enum型にするとドロップダウンリストとして表示されます。FlagsAttribute付きのenum型の場合は複数選択可能なチェックボックス付きドロップダウンリストとして表示されます。
　~~なおこのような設定は、現時点ではActivity CreatorのWizardではできませんので、手動で記述する必要があります。~~

　例えば以下を追加してビルドしてみましょう。

```
        public bool E { get; set; }

        public System.IO.SearchOption F { get; set; }

        public System.Text.RegularExpressions.RegexOptions G { get; set; }
```

UiPathの画面上は以下のようにboolはチェックボックスに、enumはドロップダウンリストになります。
![uac2-B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/a482eb8a-1b4b-8aff-f4c5-a8494565a5e0.png)

FlagsAttribute付きのenumは以下のようにチェックボックス付きドロップダウンになります。
![uac2-C.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/d4157267-1ebe-5ed3-e64a-32e8bf86161f.png)

 (2020/3/18追記)下図のようにWizardのプロパティ定義画面でDirectionをNoneにすることにより、Wizardからでも上記のようなチェックボックスやドロップダウンリストを作成できます。

![uac2-D.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477147/808232d5-e730-85dd-6e95-e8e22b814ffd.png)


デザイナー部分のプロパティ設定は、また別の機会に記述します。

（その２：終わり）

[その１](https://qiita.com/SuetakeYoichi/items/2bbd7affbbcf32e002c1)　その２　[その３](https://qiita.com/SuetakeYoichi/items/29278e6b9c5621fd2358)　[その４](https://qiita.com/SuetakeYoichi/items/117126227867d580d590)　[その５](https://qiita.com/SuetakeYoichi/items/12369209ab6fc5807ddc)　[その６](https://qiita.com/SuetakeYoichi/items/1c3f8ce5feec4c1bb36f)