ついに Power Fxのソースコードが公開されました!
自前のサービスにPower Fxを使ったユーザー自身によるカスタマイズを用意できますね!
そんなたいそうなことはできないので、WinFormsで本当に簡素なアプリを作ってみました。
今回はその時の始め方を書いていきます。 作業は Visual Studio 2019を使う前提です。
まずはサンプルアプリのダウンロード
Power Fxが公開されたのに伴い、C#で書かれたサンプルのコンソールアプリが公開されています。
ダウンロードしたらあとはVisual Studioで "ConsoleREPL.sln" を開いてビルド!と押すだけです。
実行するとコンソールが開かれてあとは馴染みのPower Appsの関数が使えます。
関数はPower Appsで使えるものすべてではなく、Power Apps特有のデータ構造などには依存しないような部分に限定されているように見えます。
サンプルの中身を見ると、処理の大部分は以下のコードで実現されていることが分かります。
// variable assignment: Set( <ident>, <expr> ) if ((match = Regex.Match(expr, @"^\s*Set\(\s*(?<ident>\w+)\s*,\s*(?<expr>.*)\)\s*$")).Success) { var r = engine.Eval(match.Groups["expr"].Value); Console.WriteLine(match.Groups["ident"].Value + ": " + PrintResult(r)); engine.UpdateVariable(match.Groups["ident"].Value, r); } // formula definition: <ident> = <formula> else if ((match = Regex.Match(expr, @"^\s*(?<ident>\w+)\s*=(?<formula>.*)$")).Success) engine.SetFormula(match.Groups["ident"].Value, match.Groups["formula"].Value, OnUpdate); // eval and print everything else, unless empty lines and single line comment (which do nothing) else if (!Regex.IsMatch(expr, @"^\s*//") && Regex.IsMatch(expr, @"\w")) { var result = engine.Eval(expr); if (result is Microsoft.PowerFx.Core.Public.Values.ErrorValue errorValue) throw new Exception("Error: " + errorValue.Errors[0].Message); else Console.WriteLine(PrintResult(result)); }
これを見ると大体どういう入力を受け付けるのか/弾くのか読み取れますね。
WinForms で使ってみる
Power Fxを使い始めるには自分のアプリにパッケージを追加してあげる必要があります。 現在はまだnuget.orgに登録されておらず、仮置き場のようです。この仮置き場をパッケージマネージャのソースに追加して、PowerFx.Core やPowerFx.Interpreter を使えるようにします。
新しいプロジェクトを作成したら、 プロジェクト > Nugetパッケージの管理 と進み
パッケージソースの追加で以下のURLを追加してあげます。
https://pkgs.dev.azure.com/ConversationalAI/BotFramework/_packaging/SDK%40Local/nuget/v3/index.json
この状態で、追加したパッケージソースにて "PowerFx" を検索、追加してあげれば準備は完了です。
あとは適当に画面を作って、処理のほとんどをサンプルから持ってくれば完成です。
躓いたところ:
PowerFxのエンジンを初期化するところで、どうすればいいんだーとなりましたが、 engine = new RecalcEngine();
としておけばいいようです。
サンプルだと "varTest = 123" みたいな入力をしたときも結果を返してくれているんですが、単純にコピーしただけではフォームのラベルに結果を表示できませんでした。engine.SetFormula(...)
している部分。
ここは、 SetFormula(...) → Eval(...) としてあげることで結果の表示ができました。
結局、フォームのボタンには以下のようなコードを書いています。
string input = textBox1.Text; var expr = input; Match match; // variable assignment: Set( <ident>, <expr> ) if ((match = Regex.Match(expr, @"^\s*Set\(\s*(?<ident>\w+)\s*,\s*(?<expr>.*)\)\s*$")).Success) { var r = engine.Eval(match.Groups["expr"].Value); Console.WriteLine(match.Groups["ident"].Value + ": " + PrintResult(r)); engine.UpdateVariable(match.Groups["ident"].Value, r); label1.Text = match.Groups["ident"].Value + ": " + PrintResult(r); } // formula definition: <ident> = <formula> else if ((match = Regex.Match(expr, @"^\s*(?<ident>\w+)\s*=(?<formula>.*)$")).Success) { engine.SetFormula(match.Groups["ident"].Value, match.Groups["formula"].Value, OnUpdate); label1.Text = PrintResult(engine.Eval(match.Groups["ident"].Value)); } // eval and print everything else, unless empty lines and single line comment (which do nothing) else if (!Regex.IsMatch(expr, @"^\s*//") && Regex.IsMatch(expr, @"\w")) { var result = engine.Eval(expr); if (result is Microsoft.PowerFx.Core.Public.Values.ErrorValue errorValue) throw new Exception("Error: " + errorValue.Errors[0].Message); else Console.WriteLine(PrintResult(result)); label1.Text = PrintResult(result); }
ということで、ソースコードが公開されてお手軽に、C#で作るアプリにPower Fxを追加できるようになったよという紹介でした。
WinFormでも #PowerFx pic.twitter.com/1oKCY4VvvI
— Hiro (@mofumofu_dance) November 4, 2021