20210417のC#に関する記事は7件です。

.NET5のWPFアプリでインタラクティブなトースト通知を実装する

つくったもの 昔作っていたWPFアプリ(.NET5)に、パッケージ化やら証明書やらのメンドクサイ作業一切なしでトースト通知を実装することができました。 #アプリ自体の説明はこちら #リポジトリはここ 実装のきっかけ  最近、UWPアプリからしか使えなかった機能がクラシックデスクトップアプリ(WinForm, WPF)でも使えるようになってきてます。トースト通知もそのひとつのようで。@okazukiさんのtweetでAPIの仕様変更を知りました。 今回手を加えたアプリを作った当時(2020年夏頃)、せっかくだからトーストも実装したいなぁ〜と考えてはいたのですがあまりのめんどくささに断念してました。 #ちなみにこんな実装が必要だったらしい...↓ というわけで、どのくらい実装がラクになっているのか、以前開発したWPFアプリにトースト通知機能を実装して確認してみます。 トースト通知を表示するところまで まずは単純なメッセージを表示するだけの機能を実装してみます。 NuGetで必要なパッケージを追加 Microsoft.Toolkit.Uwp.Notificationsパッケージを追加。 プロジェクトのターゲットフレームワークをWin10向けに変更 ←大事! 最初これを忘れていてしばらくつまづいてました... 公式の記事でも言及されてますが、変更せずに「net5.0-windows」のままになっているとToastContentBuilderのShowメソッド定義がない、とコンパイル時点で怒られます。 トースト通知する処理を実装 メッセージを表示するならこれだけでOK new ToastContentBuilder() .AddText("⏰ TimeRecorder ⏰") .AddText("作業タスクが設定されていません") .Show(); 表示イメージ ↓ すごい!めちゃ簡単! 対話型のトースト実装 実はここまでの機能(メッセージの表示のみ)だと、WinFormsのNotifyIcon.ShowBalloonTipを使ってすでに実装できてました。 ↓WinFormsのNotifyIconを利用した通知 せっかく純正Toastが使えるようになったので、トーストコントロール内で項目の選択をしてアプリ側で対応する処理を行う対話型の実装をしてみます。 UI構築 トーストにはいろいろなコンテンツを埋め込むことができるようで、リファレンスをざっと確認すると テキスト 画像 コンボボックス ボタン 通知音 など、結構自由にカスタマイズできるよう。 今回の要件に合わせてカスタマイズすると、以下のようなソースになりました。 NotificationService.cs public void PutInteractor(IEnumerable<WorkTaskWithTimesDto> workTasks) { var title = "お知らせ"; var content = "作業タスクが設定されていません"; var attribute = "TimeRecorder ⏰ 工数管理"; var selector = new ToastSelectionBox(_SelectionTaskKey); // 表示できる項目数に上限があるよう foreach(var itm in workTasks.Take(5) .Select(t => new ToastSelectionBoxItem(t.TaskId.Value.ToString(), $"[{t.ProcessName}] {t.Title}"))) { selector.Items.Add(itm); } selector.DefaultSelectionBoxItemId = selector.Items.FirstOrDefault()?.Id ?? ""; new ToastContentBuilder() .SetToastScenario(ToastScenario.Reminder) .AddText(title) .AddText(content) .AddAttributionText(attribute) .AddToastInput(selector) .AddButton(new ToastButton() .SetContent("開始") .AddArgument(_ActionTypeCode, _ActionTypeStartTask)) .AddButton(new ToastButtonSnooze()) .Show(); } ポイントとしては3点。 コンボボックスはToastSelectionBoxのItemsに項目を追加することで実装可能 ユーザが選択した内容を特定するために各コンテンツにキーを付与しておく 「再通知」するにはToastScenario.Reminderの指定が必要 上記のソースだとこんなイメージのトースト通知になります。 トーストコントロール内でのユーザー操作を検知する ToastNotificationManagerCompat.OnActivatedイベントをリッスンしておくことでトーストコントロール上のユーザ操作を検知することができます。App.xaml.csとかで購読開始して、ユーザ操作を検知したらその内容に合わせて必要な処理を行うよう実装します。 #イベントはUIスレッド以外で処理されるようなので、UIを触る場合はDispatcherを経由する必要があります。 NotificationService.cs public void Setup() { // Listen to notification activation ToastNotificationManagerCompat.OnActivated += toastArgs => { // Obtain the arguments from the notification ToastArguments args = ToastArguments.Parse(toastArgs.Argument); // Obtain any user input (text boxes, menu selections) from the notification ValueSet userInput = toastArgs.UserInput; // Need to dispatch to UI thread if performing UI operations Application.Current.Dispatcher.Invoke(delegate { if(args.TryGetValue(_ActionTypeCode, out string value)) { switch(value) { case _ActionTypeStartTask: userInput.TryGetValue(_SelectionTaskKey, out object key); StartSelectedWorkTask(key?.ToString()); break; } } else { ((MainWindow)Application.Current.MainWindow).ShowWindow(); } }); }; } private void StartSelectedWorkTask(string workTaskId) { var contents = MainWindowViewModel.Instance.Contents.OfType<WorkUnitRecorderViewModel>().First(); var selectedTask = contents.PlanedTaskCards.FirstOrDefault(c => c.Dto.TaskId.Value.ToString() == workTaskId); selectedTask?.StartOrStopWorkTask(); } ポイントは2点。 ToastArgumentsにはどのボタンを押下したかの情報が格納されている  ⇒ 今回の場合、開始ボタンを押下するとKey=_ActionTypeCode, Value=_ActionTypeStartTaskの情報が格納される ValueSetにはコンボボックスで選択した項目の情報が格納されている  ⇒ 今回の場合、選択したタスクのIDが格納される おわりに ターゲットフレームワークの変更は必要でしたが、それ以外は数十行のコードを書くだけでトースト通知が実装できました!去年の状況からは想像もできない簡単さですねぇ。 一時期は「クラシックデスクトップアプリ」なんて呼ばれてしまっていたWPFですが、Microsoftの方針転換のおかげで最新機能が簡単に実装できるようになってきてます。WPF、まだまだイケるぞ! 参考サイト
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ZIPファイルの中身を解凍する

先日、windowsのCドライブのディスクが枯渇する問題がありました。 原因は凡ミスでTEMPファイルを大量生成していたのですが。。。 その関連でCドライブの%TEMP%にファイルを作成せずにZIPファイルを解凍する方法があったので書き込みます。 まず、ZipArchiveを使えるようにするため、以下を参照します。 System.IO.Compression System.IO.Compression.FileSystem そして、以下のコードを書きます。 var file = @"comp.zip"; using (ZipArchive archive = ZipFile.OpenRead(file)) { var f = archive.GetEntry("comp.txt"); var ms = f.Open(); using (var fileStream = new FileStream("output.txt", FileMode.CreateNew, FileAccess.ReadWrite)) { ms.CopyTo(fileStream); } } これで、comp.zipにあるcomp.txtをoutput.txtに書き出すことができます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【C#】「さっ!」とデータを保存しよう!

初めに プログラムでデータを保存したいことがありませんか? ただ、あまり簡単にする方法が見つかりにくい気がします なのでまとめます。あくまで、簡単に「さっ」と実装する方法です 本編 初めから保存するプログラムを行きましょう プログラム XMLClass public static class XMLClass { public static string SaveToString<T>(T control) { var writer = new StringWriter(); // 出力先のWriterを定義 var serializer = new XmlSerializer(typeof(T)); serializer.Serialize(writer, control); var xml = writer.ToString(); Console.WriteLine(xml); return xml; } public static T LoadFromString<T>(string xml) { var serializer = new XmlSerializer(typeof(T)); var deserializedBook = (T)serializer.Deserialize(new StringReader(xml)); return deserializedBook; } } これがプログラムとなります。 これはファイルへの保存は含まれていません、 なのでファイルへの読み書きは自分で実装する必要がありますが 文字列化してしまえば、ファイルへの読み書きが簡単にでき、文字列であればいろいろな場面で使えるためこのようにしました ジェネリックで型を指定するため基本的にほとんどの型に対応しています 使い方 これはstaticのクラスなので、インスタンスなしに実行できます サンプルプログラムを以下に示します Sample using System; using System.IO; using System.Xml.Serialization; class Sapmle { void Main() { //セーブするデータを作成 SaveData save = new SaveData(); save.data ="hogehoge"; save.number = 100; //データをXML化 string xml=XMLClass.SaveToString<SaveData>(save); //データをxmlから復元 SaveData sdata =XMLClas.LoadFromString<T>(string s); //データの確認 Console.WriteLine(sdata.data); Console.WriteLine(sdata.number); } } class SaveData { public string data; public int number; } このように使うことができます ファイルへはstring型のxmlの変数内に入った文字列をファイルに出力することで保存することが可能です 注意点 WPFやForm,Refrectionなど一部例外が発生し保存できないものがあるのでご注意ください また保存させたくない場合は [System.Xml.Serialization.XmlIgnore] の属性を付けることで保存させないことが可能です 終わりに かなり雑にですがC#での簡単なデータ保存の方法をまとめました、 何かご不明な点などがございましたらコメントまでお願いします。 最後までご覧いただきありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【.NET/C#】メソッドのパフォーマンスを簡単に集計するライブラリの紹介

概要 BenchmarkDotNetの紹介と使い方を掲載する。 BenchmarkDotNetはメソッドのパフォーマンスを簡単に計測できるライブラリです。 統計的な情報をレポートしてくれるため、関数のパフォーマンスを調査する業務で役立ちそう。 BenchmarkDotNetとは? BenchmarkDotNetは、メソッドをベンチマークに変換し、そのパフォーマンスを追跡し、 再現性のある測定実験を共有するのに役立ちます。 上記はGitHubの記載内容の機械翻訳 サポート対象は下記。.NET系なら大体使えそう。 本記事ではC#で実装する。 Projects: classic and modern with PackageReferences Runtimes: Full .NET Framework (4.6+), .NET Core (2.0+), Mono, CoreRT OS: Windows, Linux, MacOS Languages: C#, F#, VB 本記事では試しませんが、エクスポート機能も充実している。 手順 下記ドキュメントのOverViewに従って、パフォーマンス計測を行う。 BenchmarkDotNetの公式ドキュメント 1.NuGetパッケージをインストール Visual Studioを立ち上げ、「コンソールアプリケーション」を選択する。 下記のNuGetパッケージを追加する。 NuGetリンク 2.計測対象のメソッドを含むクラスを作成する 扱う題材(計測対象) stringとStringBuilderの文字列結合の処理時間を比較する。 期待結果は「StringBuilderの方がパフォーマンスが優れる」こと。 ※下記サイトで既に検証済み 文字列処理を高速に行う StringBuilderがパフォーマンスが優れる理由 下記の違いにより、扱う文字の数が増えるとStringBuilderの方がパフォーマンスに優れることが多い。 ・string型は編集不可なため、文字列操作の度に新たなインスタンスを作る。 ・StringBuilderは編集可能であるため、文字列操作で新たなインスタンスを作らない。 stringとStringBuilderの違い 計測対象のクラスを定義する 計測対象のメソッド含むクラスを定義する。 対象メソッドには[Benchmark]属性を指定する。 using BenchmarkDotNet.Attributes; using System.Text; public class StringConcatMesurement { private int NumberOfItems = 200000; [Benchmark] public string WithStringBuilder() { var sb = new StringBuilder(); for (int i = 0; i < NumberOfItems; i++) { sb.Append("1"); } return sb.ToString(); } [Benchmark] public string WithStringType() { string s = string.Empty; for (int i = 0; i < NumberOfItems; i++) { s += "1"; } return s; } } メイン関数からコールする using BenchmarkDotNet.Running; class Program { static void Main(string[] args) { var summary = BenchmarkRunner.Run<StringConcatMesurement>(); } } これで準備完了!!実行する前に一点だけ注意事項。 [リリースビルド]で実行すること。 [デバックビルド]の場合は、下記のように実行時エラーになる。 ちなみに、このままの状態で実行すると私の環境で10分以上掛かった。 ベンチマーク計測に正確さが必要ない場合、[ShortRunJob]属性をつけて下さい(後述の項「計測時間の短縮をする方法」を参照)。 計測開始時 計測終了時 計測結果を確認する 下記の結果が表示される。 ・実行環境 ・統計情報の表(関数名、平均値、エラー、標準偏差) ・統計情報のラベルの説明 // * Summary * BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.867 (2004/?/20H1) Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores .NET Core SDK=3.1.402 [Host] : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT DefaultJob : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT | Method | Mean | Error | StdDev | |------------------ |---------------:|--------------:|--------------:| | WithStringBuilder | 895.1 us | 15.62 us | 21.90 us | | WithStringType | 7,806,015.2 us | 155,282.10 us | 347,310.67 us | // * Hints * Outliers StringConcatMesurement.WithStringBuilder: Default -> 4 outliers were removed (978.11 us..1.02 ms) StringConcatMesurement.WithStringType: Default -> 4 outliers were removed (9.74 s..10.10 s) // * Legends * Mean : Arithmetic mean of all measurements Error : Half of 99.9% confidence interval StdDev : Standard deviation of all measurements 1 us : 1 Microsecond (0.000001 sec) 予想通りStringBuilderの方がパフォーマンスが優れる。 平均値で比較すると、約8721倍StringBuilderが速い。 標準偏差を見ても、stringに比べると計測結果のバラツキが小さいことが分かる。 計測結果サマリをカスタマイズする サマリーは下記の詳細結果のうち、属性でどれを出すかを指定する。 デフォルトだと、平均値、エラー、標準偏差を表示する。 試しに最小値、最大値を追加する。 // * Detailed results * StringConcatMesurement.WithStringBuilder: DefaultJob Runtime = .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT; GC = Concurrent Workstation Mean = 830.978 us, StdErr = 3.726 us (0.45%), N = 15, StdDev = 14.432 us Min = 809.898 us, Q1 = 821.067 us, Median = 826.252 us, Q3 = 844.369 us, Max = 855.115 us IQR = 23.303 us, LowerFence = 786.113 us, UpperFence = 879.323 us ConfidenceInterval = [815.549 us; 846.406 us] (CI 99.9%), Margin = 15.428 us (1.86% of Mean) Skewness = 0.28, Kurtosis = 1.64, MValue = 2 -------------------- Histogram -------------------- [802.218 us ; 834.536 us) | @@@@@@@@@@ [834.536 us ; 857.584 us) | @@@@@ --------------------------------------------------- StringConcatMesurement.WithStringType: DefaultJob Runtime = .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT; GC = Concurrent Workstation Mean = 7.206 s, StdErr = 0.051 s (0.70%), N = 95, StdDev = 0.493 s Min = 6.459 s, Q1 = 6.804 s, Median = 7.101 s, Q3 = 7.443 s, Max = 8.521 s IQR = 0.639 s, LowerFence = 5.846 s, UpperFence = 8.402 s ConfidenceInterval = [7.034 s; 7.378 s] (CI 99.9%), Margin = 0.172 s (2.38% of Mean) Skewness = 0.84, Kurtosis = 3.15, MValue = 2.93 -------------------- Histogram -------------------- [6.317 s ; 6.608 s) | @@@@ [6.608 s ; 6.891 s) | @@@@@@@@@@@@@@@@@@@@@@@@ [6.891 s ; 7.243 s) | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ [7.243 s ; 7.605 s) | @@@@@@@@@@@@@@@@@@@ [7.605 s ; 7.892 s) | @@@@@@@ [7.892 s ; 8.269 s) | @@@@@@@ [8.269 s ; 8.663 s) | @@@ --------------------------------------------------- サマリーのカスタマイズ実装 [MinColumn,MaxColumn]//←新規追加 public class StringConcatMesurement { private int NumberOfItems = 200000; [Benchmark] public string WithStringBuilder() { //略 } [Benchmark] public string WithStringType() { //略 } } カスタマイズ後のサマリー 最小値、最大値の項目が増えた。 | Method | Mean | Error | StdDev | Min | Max | |------------------ |---------------:|--------------:|--------------:|---------------:|---------------:| | WithStringBuilder | 831.0 us | 15.43 us | 14.43 us | 809.9 us | 855.1 us | | WithStringType | 7,205,897.0 us | 171,677.49 us | 492,574.91 us | 6,458,541.9 us | 8,520,846.9 us | 計測時間の短縮をする方法 関数のパフォーマンスを改善する場面などでは、正確性よりも試行回数が重視されると思う。 何も制限なしで使うと、文字列の結合の評価だけで約10分かかった。 とても待ってられない。 下記[ShortRunJob]属性指定することで、関数の試行回数(N=3)で固定されて計測時間を短縮できる。 [ShortRunJob]属性指定 [ShortRunJob]//←これ [MinColumn, MaxColumn] public class StringConcatMesurement { //(略) } [ShortRunJob]属性指定前の計測時間 Global total time: 00:10:46 (646.11 sec), executed benchmarks: 2 [ShortRunJob]属性指定後の計測時間 Global total time: 00:00:57 (57.23 sec), executed benchmarks: 2 参考にしたサイト BenchmarkDotNetの公式ドキュメント How to benchmark C# code using BenchmarkDotNet @neueccさんが書いたベンチマークの測り方 文字列処理を高速に行う stringとStringBuilderの違い
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C# VisualStudioでprotoファイルからソースコードとAPI仕様書を生成する

このドキュメントの内容 VisualStudio のプロジェクトテンプレートに「gRPCサービス」が追加され、gRPC を使ったアプリケーションの開発がしやすくなりましたが、このテンプレートはサービスアプリケーション用のものであるため、ライブラリを作成したい場合には無駄な実装が含まれてしまいます。ライブラリ用のテンプレートで proto ファイルからソースコードを生成する方法を説明します。加えて、proto-gen-doc を利用してAPI仕様書を出力する方法も説明します。 環境 使用した環境は次の通りです。 Microsoft Visual Studio Community 2019 Version 16.8.2 Grpc.AspNetCore のバージョンは 2.36.0 です。 手順 テンプレート「クラスライブラリ(.NET Core)」を選択して新規プロジェクトを作成します。 プロジェクトのプロパティを開き、対象のフレームワークを次の中から選択します。Grpc.AspNetCore は .NET Standard や .NET Framework をサポートしていません。 .NET Core 3.0 .NET Core 3.1 .NET 5 NuGet で Grpc.AspNetCore をインストールします。 プロジェクト内に proto ファイルを配置するフォルダを作成します。フォルダを作成するのは管理しやすくするためだけであり、フォルダ名に規約はありません。 proto ファイルを追加します。アイテムテンプレートに proto はないようです。「テキストファイル」でよいと思います。拡張子を proto とするとソリューションエクスプローラー上のアイコンが変わりますので、ファイルの種類を認識しているとは考えられます。 ファイルのビルドアクションを「Protobuf compiler」に変更します。リストアップされるプロパティ群が Protobuf に対応したものに変わります。 proto ファイルに IDL を記述します。 プロジェクトをビルドまたはリビルドすると IDL からソースコードが生成されます。cs ファイルはプロジェクトには追加されず、プロジェクトの obj フォルダ配下に出力されます。「カスタムツールの実行」では生成されませんでした。 ライブラリを使用するアプリケーションの参照アセンブリに dll ファイルを追加します。 partial メンバーを追加するには 生成されたクラスに対して partial メンバーを追加するには、いったんビルドした後で partial クラスを追加します。 Grpc.Tools で生成されるソースコードとの違い 全てのデータ型に対して確認してはいませんが、生成されるソースコードの実装は同じであるようです。 Grpc.AspNetCore は Grpc.Core には依存していませんが、Grpc.Core.Api と Grpc.Tools を利用しています。 Grpc.AspNetCore 2.36.0 Google.Protobuf 3.15.5 Grpc.AspNetCore.Server.ClientFactory 2.36.0 Grpc.AspNetCore.Server 2.36.0 Grpc.Net.Common 2.36.0 Grpc.Core.Api 2.36.1 Grpc.Net.ClientFactory 2.36.0 Grpc.Net.Client 2.36.0 Grpc.Net.Common 2.36.0 Grpc.Core.Api 2.36.1 Microsoft.Extensions.Http 3.0.3 Grpc.Tools 2.36.1 proto ファイルのインポート ある proto ファイルの中で別のファイルに定義された型を参照するには、そのファイルをインポートする必要があります。 既知の型のインポート Nuget でインストールされた Grpc.Tools (2.36.1) のパッケージフォルダ内には以下のファイルが組み込まれています。 any.proto api.proto descriptor.proto duration.proto empty.proto field_mask.proto source_context.proto struct.proto timestamp.proto type.proto wrappers.proto これらのファイルをインポートするには import を記述すればよいです。 sample.proto import "google/protobuf/timestamp.proto"; message SampleMessage { google.protobuf.Timestamp Time = 1; } 独自の proto ファイルを無理やりパッケージフォルダに配置する Grpc.Tools のパッケージフォルダに上記以外のファイルを配置してインポートすると、IDL 上のエラーにはならないものの生成されたソースコード内でコンパイルエラーが発生します。 次の GuidValue.proto を Grpc.Tools のパッケージフォルダに配置してインポートすると、 GuidValue.proto syntax = "proto3"; package example.protobuf; message GuidValue { string Value = 1; } sample.proto import "google/protobuf/timestamp.proto"; import "google/protobuf/GuidValue.proto"; message SampleMessage { google.protobuf.Timestamp Time = 1; example.protobuf.GuidValue id = 2; } 次のような SampleMessage クラスのソースコードが生成されますが、Example.Protobuf.GuidValue クラスや Example.Protobuf.GuidValueReflection クラスが生成されず、コンパイルエラーになります。GuidValue.proto がプロジェクトに含まれていないためです。 public sealed partial class SampleMessage : pb::IMessage<SampleMessage> { /// <summary>Field number for the "id" field.</summary> public const int idFieldNumber = 2; private global::Example.Protobuf.GuidValue id_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Example.Protobuf.GuidValue id { get { return id_; } set { id_ = value; } } } 独自の proto ファイルをプロジェクト内に配置する 前述の GuidValue.proto をプロジェクト内に配置します。 プロジェクト構成 ProjectRoot proto sample.proto GuidValue.proto GuidValue.proto をインポートする場合、フォルダ名/ファイル名 で指定します。 sample.proto import "google/protobuf/timestamp.proto"; import "proto/GuidValue.proto"; message SampleMessage { google.protobuf.Timestamp Time = 1; example.protobuf.GuidValue ID = 2; } ソースコードが生成され、ビルドも成功します。 複数のプロジェクトで型を共用する 前述の GuidValue のような汎用的な型は、複数のプロジェクトで共用できると便利です。 各プロジェクトに GuidValue.proto を含めると、それぞれのアセンブリに GuidValue 型が定義されます。それらのアセンブリを一つのプロジェクトから参照しようとすると、型の重複が発生してしまいます。 共用したい型を定義したプロジェクトを作り、アセンブリを参照させることで型を共用できます。 共用したい型を定義するプロジェクトを作成します。CommonLibrary.csproj とします。 CommonLibrary.csproj に GuidValue.proto を追加します。 CommonLibrary.csproj をビルドします。 GuidValue 型を使用するプロジェクトを作成します。SampleLibrary.csproj とします。 SampleLibrary.csproj の参照に CommonLibrary.dll を追加します。 SampleLibrary.csproj に GuidValue.proto を追加します。GuidValue 型を生成対象から除外するため、GuidValue.proto のプロパティを変更します。 gRPC Stub Classes プロパティに Do not generate を設定します。 Compile Protobuf プロパティに false を設定します。 SampleLibrary.csproj をビルドします。 CommonLibrary.csproj CommonLibrary proto GuidValue.proto SampleLibrary.csproj SampleLibrary proto sample.proto GuidValue.proto // sample.proto のソースコード生成のためにファイルを追加。コンパイル対象外にします。 なお、上記の手順では各プロジェクトに GuidValue.proto ファイルがコピーされます。リンクファイルとしてプロジェクトに追加できるとよいのですが、リンクファイルは Grpc.Tools から読み取ることができないようで「ファイルが見つからない」エラーが発生してしまいます。 API仕様書を出力する proto ファイルで定義した内容をドキュメントに出力できると便利です。proto-gen-doc を利用することが多いと思いますが、これをビルド時に呼び出す方法を紹介します。proto-gen-doc に対応していそうなライブラリを Nuget で探してみましたが見つかりませんでしたので、プロジェクトのビルド後イベントを利用することにしました。 proto-gen-doc を GitHub から入手し、適当なフォルダに展開します。 バッチファイル proto-gen-doc.bat を作成し、プロジェクトのビルド後イベントに次のコマンドを記述します。 ビルド後イベント proto-gen-doc.bat $(Protobuf_ProtocFullPath) $(Protobuf_StandardImportsPath) $(ProjectDir) proto-gen-doc.bat rem protoc.exe の絶対パス。 rem プロジェクトが参照している Grpc.Tools に対応するパスがマクロ $(Protobuf_ProtocFullPath) によって引き渡されます。 set PROTOC=%1 rem 標準サポートされているインクルードファイルの格納ディレクトリの絶対パス。 rem プロジェクトが参照している Grpc.Tools に対応するパスがマクロ $(Protobuf_StandardImportsPath) によって引き渡されます。 set WELLKNOWN_PROTO_DIR=%2 rem proto-gen-doc の格納ディレクトリ。 rem マクロではサポートされていないため直接指定しています。 set PROTOC_GEN_DOC_DIR=E:\ProgramFiles\proto-gen-doc rem proto-gen-doc の実行ファイル。 set PLUGIN_PROTOC_GEN_DOC=protoc-gen-doc.exe rem proto-gen-doc のカスタムテンプレート。 set MARKDOWN_TEMPLATE=CustomMarkdownTemplate.tmpl rem プロジェクトディレクトリの絶対パス。マクロ $(ProjectDir) によって引き渡されます。 set PROJECT_DIR=%3 rem 出力対象の proto ファイル。 rem プロジェクトディレクトリ配下の proto フォルダに格納されている proto ファイルを対象とします。 set PROTO_FILE=%PROJECT_DIR%proto\*.proto rem ドキュメント出力先のパス。プロジェクトディレクトリ配下の doc フォルダとしました。 set OUT_DIR=%PROJECT_DIR%doc rem proto-gen-doc ディレクトリをカレントディレクトリに設定します。 rem テンプレートファイルを絶対パスで指定する方法がわからず、 rem 実行ファイルとテンプレートファイルを同じフォルダに配置し、 rem カレントディレクトリにする方法をとりました。 cd %PROTOC_GEN_DOC_DIR% rem ドキュメント出力ディレクトリを生成します。 if not exist %OUT_DIR% mkdir %OUT_DIR% rem 個々の proto ファイルごとにドキュメントを出力する場合 for /f "usebackq tokens=* delims=0123456789 eol=" %%i in (`dir /B /S %PROTO_FILE%`) do ( rem html形式で出力します call %PROTOC% -I=%WELLKNOWN_PROTO_DIR% -I=%PROJECT_DIR% -I=%%~dpi --doc_out=html,%%~ni.html:%OUT_DIR% "%%i" --plugin=protoc-gen-doc="%PLUGIN_PROTOC_GEN_DOC%" rem markdown形式で出力します call %PROTOC% -I=%WELLKNOWN_PROTO_DIR% -I=%PROJECT_DIR% -I=%%~dpi --doc_out=markdown,%%~ni.md:%OUT_DIR% "%%i" --plugin=protoc-gen-doc="%PLUGIN_PROTOC_GEN_DOC%" rem カスタムテンプレートを使用して出力します call %PROTOC% -I=%WELLKNOWN_PROTO_DIR% -I=%PROJECT_DIR% -I=%%~dpi --doc_out=%MARKDOWN_TEMPLATE%,%%~ni.custom.md:%OUT_DIR% "%%i" --plugin=protoc-gen-doc="%PLUGIN_PROTOC_GEN_DOC%" ) rem 一つのドキュメントに出力する場合 rem html形式で出力します call %PROTOC% -I=%WELLKNOWN_PROTO_DIR% -I=%PROJECT_DIR% --doc_out=html,all.html:%OUT_DIR% %PROTO_FILE% --plugin=protoc-gen-doc="%PLUGIN_PROTOC_GEN_DOC%" rem markdown形式で出力します call %PROTOC% -I=%WELLKNOWN_PROTO_DIR% -I=%PROJECT_DIR% --doc_out=markdown,all.md:%OUT_DIR% %PROTO_FILE% --plugin=protoc-gen-doc="%PLUGIN_PROTOC_GEN_DOC%" rem カスタムテンプレートを使用して出力します call %PROTOC% -I=%WELLKNOWN_PROTO_DIR% -I=%PROJECT_DIR% --doc_out=%MARKDOWN_TEMPLATE%,all.custom.md:%OUT_DIR% %PROTO_FILE% --plugin=protoc-gen-doc="%PLUGIN_PROTOC_GEN_DOC%" まとめ 任意のプロジェクトテンプレートからも proto ファイルからのソースコードを生成することができることを確認しました。 コマンドラインツールを使わずに Visual Studio 上の操作だけで処理できるのは便利ですが、できることは制限されるようです。 参考リンク
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【メモ】.NET/C#の情報収集に利用するサイトまとめ

記事の概要 c#/.NET関連の情報収集に利用しているサイトのメモを共有する。 (本記事に記載ある方々、勝手にリンクを貼り不快に思われたら、大変申し訳ありません。 その際はコメントに記載を下さい。リンク削除します。) 背景 Quiitaの投稿をはじめてから、情報の正誤を調査するために触れる媒体が増えた。 その中で感じたことは、下記2つ。 1.「英語」ってだけで敬遠していた情報の中に素晴らしいものが多い。 同時に、翻訳が出るまで待ってたら、「技術の進歩に取り残される」って危機感を持った。 2.膨大なMicrosoftの公式ドキュメントの海を漂うより、その道に知見者のサイトを探した方が  答えに辿り着くのが早いこともある。  国内と国外のウォッチしている方のサイトを記載する。 蛇足 会社の先輩の助言を受けて、2021/03からコミュニティに参加し始めた。短い時間で有益な情報を知る良い機会になると感じた。個人的に役に立ったコミュニティーを随時追記していきます。 Microsoft公式ブログ Microsoft Developer Blogs 最新情報の入手に役立ちそう。直近だと、Visual Studio2020の発表が流れた@2021/04/19。 Microsoft Developer Blogs Visual Studio 2022 コミュニティ .NETラボ 勉強会 .NET技術やマイクロソフト製品について勉強するコミュニティー。最近参加し始めた。 とても勉強になる。 開催日は毎月第4土曜日。connpassに登録して、グループ登録すれば資料を参照できる。 .NETラボ 勉強会 マガジン Visual Studio Magazine Visual Studio関係技術を知りたいときに使う リンク MSDNマガジン Microsoftの技術を開発者が紹介した公式の記事。2019年頃に廃刊になってるが、開発に役立つノウハウを紹介した記事も多い。 リンク YouTube Microsoft Developer Microsoftの開発者が発信してるチャンネル。 チャンネル dotNET .NET系の情報が多数。C#関連を見たいときは、CSharpFritzを観る。 チャンネル .NET Foudation Microsoftのカンファレンス「.NET Conf」の動画が上がってたりする。 チャンネル Microsoft Visual Studio Visual Studioについて知りたいときに観る。 チャンネル NDC Conferences 私見だが、Microsoftの技術に詳しい人がよく登壇している。 チャンネル Update Conference Prague 私見だが、Microsoftの技術に詳しい人がよく登壇している。 チャンネル Nick Chasas Microsoft MVP の方のチャンネル。C#コーディングに関する投稿が多数。 チャンネル プロフィール IAmTimCorey Microsoft MVP の方のチャンネル。C#コーディングに関する投稿が多数 チャンネル プロフィール Raw Coding C#コーディングに関する投稿が多数 チャンネル ウォッチしている知見者の方々 ここに記載した方以外にもすごい方々はいらっしゃいますが、時間足らず巡回できていないです。 国内の知見者サイト 岩永 信之さん 知っている方が多数いらっしゃると思いますが、下記サイトのオーナーさんです。 未確認飛行 YouTueチャンネル MVPページ 河合 宣文さん OSS開発が中心のブログ。書いてある内容がとても勉強になる。 赤と黒のブログデザインが特徴的。 SlideShare MVPページ 鈴木 孝明さん FastEnumの作者さん。今日からできる!簡単.NET高速化Tipsなど役立つトピックを発信してる。 ブログより講演スライドを見ることが多い。 SlideShare MVPページ 出井 秀行さん 書籍:実戦で役立つ C#プログラミングのイディオム/定石&パターンの著者さん。 書籍には、いつも大変お世話になっております。 Quiita MVPページ 国外の知見者サイト Joydip Kanjilalさん How to 的な内容の記事が多い。比較的に新しい技術のものが多いので、助かる。 ブログ VINCENT MAVERICK DURANOさん CodeProjectでMVPに輝くなど情報のアウトプット量が非常に多い方。 ブログには、ASP.NET関連の投稿内容が多い。 ブログ CodeProject プロフィール Adam Sitnikさん BenchmarkDotNetの作者さん。Microsoft .NETチームの方みたい。 パフォーマンス周りの投稿が多い。 ブログ Kevin Gosseさん デバック、パフォーマンスの知見者の方みたい。 また読みたいと思ったブログの記事は以下。 Performance best practices in C# .NET ThreadPool starvation, and how queuing makes it worse ブログ プロフィール Steve Gordonさん .NET Core/ASP.NETの投稿が中心。Turbocharged: Writing High-Performance C# and .NET Codeって講演をしている。 ブログ プロフィール Brandon Minnickさん Xamarinの投稿が中心。 Microsoft社のXamarinの開発者のようです。 ブログ プロフィール Konrad Kokosaさん Pro .NET Memory Managemenという書籍の著者さん。 ブログもメモリ関連投稿が多い。 High-performance code design patterns in C#というタイトルの講演動画を拝見する。 プロフィール Steven Smithさん ASP.NETやクラウドのアーキテクチャの知見者。 SlideShareにアーキテクチャに関する資料を投稿している。 スライド ブログ プロフィール 変更履歴 2021/04/18 記事の投稿 2021/04/19 Microsoft MVPの方にMVPページへのリンクを追加した。 MVPの活動はMicrosoftが記録しているため、発信内容を後から追いやすい。 2021/04/20 Microsoft Developer Blogを追加 コミニティも記載することにしいた。.NETラボ勉強会を追加
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【メモ】.NET/C#の情報収集に利用するサイト

概要 c#/.NET関連の情報収集に利用しているサイトのメモを情報共有する。 基本、無料かつサイト登録が不要なものを掲載。 背景 Quiitaの投稿をはじめてから、情報の正誤を調査するために触れる媒体が増えた。 その中で感じたことは、下記2つ。 1.「英語」ってだけで敬遠していた情報の中に素晴らしいものが多い。 同時に、翻訳が出るまで待ってたら、「技術の進歩に取り残される」って危機感を持った。 2.膨大なMicrosoftの公式ドキュメントの海を漂うより、その道に知見者のサイトを探した方が  答えに辿り着くのが早いこともある。  海外の人はブログなどで情報発信をよく行っている。ものすごく、ありがたい!! マガジン Visual Studio Magazine Visual Studio関係技術を知りたいときに使う リンク MSDNマガジン Microsoftの技術を開発者が紹介した公式の記事。2019年頃に廃刊になってるが、開発に役立つノウハウを紹介した記事も多い。 リンク YouTube Microsoft Developer Microsoftの開発者が発信してるチャンネル。 チャンネル dotNET .NET系の情報が多数。C#関連を見たいときは、CSharpFritzを観る。 チャンネル .NET Foudation Microsoftのカンファレンス「.NET Conf」の動画が上がってたりする。 チャンネル Microsoft Visual Studio 名前のまんま、Visual Studioについて知りたいときに観る。 チャンネル NDC Conferences 私見だが、Microsoftの技術に詳しい人がよく登壇している。 チャンネル Update Conference Prague 私見だが、Microsoftの技術に詳しい人がよく登壇している。 チャンネル Nick Chasas Microsoft MVP のチャンネル。C#コーディングに関する投稿が多数。 チャンネル IAmTimCorey Microsoft MVP のチャンネル。C#コーディングに関する投稿が多数 チャンネル Raw Coding Microsoft MVP のチャンネル。C#コーディングに関する投稿が多数 チャンネル 国内の知見者サイト 岩永 信之さん みんな大好き、未確認飛行 河合 宣文さん OSS開発が中心のブログ。書いてある内容がとても勉強になる。 赤と黒のデザインが特徴的。 SlideShare 鈴木 孝明さん FastEnumの作者さん。今日からできる!簡単.NET高速化Tipsなど役立つトピックを発信してる。 ブログより講演スライドを見ることが多い。 SlideShare 国外の知見者サイト Joydip Kanjilalさん How to 的な内容の記事が多い。比較的に新しい技術のものが多いので、助かる。 ブログ VINCENT MAVERICK DURANOさん CodeProjectでMVPに輝くなど情報のアウトプット量が非常に多い方。 ブログには、ASP.NET関連の投稿内容が多い。 ブログ CodeProject Adam Sitnikさん BenchmarkDotNetの作者さん。パフォーマンス周りの投稿が多い。 ブログ Kevin Gosseさん .NETのパフォーマンス絡みが多い ブログ Steve Gordonさん .NET Core/ASP.NETの投稿が中心 ブログ Brandon Minnickさん Xamarinの投稿が中心。MicrosoftのXamarinの中の人みたい。 ブログ Konrad Kokosaさん メモリ関連の記事多い ブログ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む