- 投稿日:2020-05-31T22:53:07+09:00
RaspberryPi センサーサンプルプロジェクト URLまとめ
RaspberryPi センサーサンプルプロジェクト URLまとめ
センサーのサンプルプロジェクトファイルをWeb上で配布している会社のまとめです。
基本どの会社のセットもCDの中にサンプルを収録しセットに付いてきます。OSOYOO
OSOYOO(オソヨー) Raspberry Pi 学ぶ電子工作キット 初心者演習用パーツセット ラズパイ11実例 回路配線図とサンプルスケッチ有り プログラミング ラズベリー パイ 超入門 スターター学習キット LED制御 スイッチ I2C LCD 温湿度センサー マイクロサーボ 人体感知センサー A/Dコンバータ ブザー 大気圧センサー リレーモジュール制御 赤外線リモコン等IoTを実践する電子部品セット (Pi 3 DIY Kit 22in1)
Project FileELEGOO
ELEGOO Arduino用のMega2560スタータキット最終版 初心者向け、チュートリアル付、MEGA 2560ボード, LCD1602
Project FileKuman
Kuman 44個キット センサー キット Raspberry Pi用 センサーモジュール スターター キット iot学習キット 電子工作 Raspberry Pi 4 B 3 2 Model B B+ A A+に適用 ラズベリーパイ K47
Project Filesunfounder
SunFounder Raspberry pi スターター電子工作キット,ラズベリーパイ初心者向けプログラミング,詳細な教本と豊富な学習用レッスン付き,Raspberry pi 4B/3B+/3B/3A+/2B/1B+/1A+/Zero W/Zeroに対応、C/Pythonコードをサポート
Project FileKeeYees
KeeYees 電子工作キット 初心者向け スターターキット 電子部品 基本部品56種類 エレクトロニクス入門キット Electronics Fun Kit Arduino用 Raspberry Pi用 チュートリアルあり
Project FileFreenove
Freenove Raspberry Pi 4 B 3 BのためのRFIDスターターキット +、423ページ詳細ガイド、Python C Java、204アイテム、53プロジェクト、エレクトロニクスとプログラミングを学ぶ、ソルダーレスブレッドボード
Project FileKEYESTUDIO
KEYESTUDIO ラズベリーパイ 拡張ボード スターターキット for Raspberry Pi 3 4 4B 電子工作 電子部品 キット 実験キット LED, 超音波 センサー, RFID モジュール,ブレッドボード セット
Project FileWayinTop
WayinTop Raspberry Pi用センサーキット 電子工作キット ラズベリー パイ 超入門 初心者向け 中級者向け 学習キット 電子部品セット プログラミング JAVA C++ Python 日本語チュートリアル
Web上未確認 CD教材UNIROI
UNIROI arduino/Raspberry Pi用 電子キット 40種セット 初心者 R3 PNP S8550+電解コンデンサ+電源モジュール 電子工作 キット ブレッドボード mega 3 2 model B A A+ +に互換 UA001
Web上未確認 CD教材Miuzei
Miuzei 初心者スターターキット mega2560 r3 nanoと互換できる(日本語マニュアル付き)
Web上未確認 CD教材
- 投稿日:2020-05-31T22:53:07+09:00
RaspberryPi センサーサンプルファイル配布 URLまとめ
RaspberryPi センサーサンプルファイル配布 URLまとめ
センサーをまとめ売りしている業者はサンプルファイルをCDに収録しセット売りしているのですが、Web上にもファイルを公開している会社をまとめてみました。
OSOYOO
OSOYOO(オソヨー) Raspberry Pi 学ぶ電子工作キット 初心者演習用パーツセット ラズパイ11実例 回路配線図とサンプルスケッチ有り プログラミング ラズベリー パイ 超入門 スターター学習キット LED制御 スイッチ I2C LCD 温湿度センサー マイクロサーボ 人体感知センサー A/Dコンバータ ブザー 大気圧センサー リレーモジュール制御 赤外線リモコン等IoTを実践する電子部品セット (Pi 3 DIY Kit 22in1)
Project FileELEGOO
ELEGOO Arduino用のMega2560スタータキット最終版 初心者向け、チュートリアル付、MEGA 2560ボード, LCD1602
Project FileKuman
Kuman 44個キット センサー キット Raspberry Pi用 センサーモジュール スターター キット iot学習キット 電子工作 Raspberry Pi 4 B 3 2 Model B B+ A A+に適用 ラズベリーパイ K47
Project Filesunfounder
SunFounder Raspberry pi スターター電子工作キット,ラズベリーパイ初心者向けプログラミング,詳細な教本と豊富な学習用レッスン付き,Raspberry pi 4B/3B+/3B/3A+/2B/1B+/1A+/Zero W/Zeroに対応、C/Pythonコードをサポート
Project FileKeeYees
KeeYees 電子工作キット 初心者向け スターターキット 電子部品 基本部品56種類 エレクトロニクス入門キット Electronics Fun Kit Arduino用 Raspberry Pi用 チュートリアルあり
Project FileFreenove
Freenove Raspberry Pi 4 B 3 BのためのRFIDスターターキット +、423ページ詳細ガイド、Python C Java、204アイテム、53プロジェクト、エレクトロニクスとプログラミングを学ぶ、ソルダーレスブレッドボード
Project FileKEYESTUDIO
KEYESTUDIO ラズベリーパイ 拡張ボード スターターキット for Raspberry Pi 3 4 4B 電子工作 電子部品 キット 実験キット LED, 超音波 センサー, RFID モジュール,ブレッドボード セット
Project FileWayinTop
WayinTop Raspberry Pi用センサーキット 電子工作キット ラズベリー パイ 超入門 初心者向け 中級者向け 学習キット 電子部品セット プログラミング JAVA C++ Python 日本語チュートリアル
Web上未確認 CD教材UNIROI
UNIROI arduino/Raspberry Pi用 電子キット 40種セット 初心者 R3 PNP S8550+電解コンデンサ+電源モジュール 電子工作 キット ブレッドボード mega 3 2 model B A A+ +に互換 UA001
Web上未確認 CD教材Miuzei
Miuzei 初心者スターターキット mega2560 r3 nanoと互換できる(日本語マニュアル付き)
Web上未確認 CD教材
- 投稿日:2020-05-31T22:06:56+09:00
C# 変数と宣言
C# 変数
変数とは?
数値や文字などを格納しておく箱のようなもの。
(それに名前を付けた物)宣言の書き方
宣言方法 例 2つの変数の宣言 int a; int b; int a,b; 一つの変数の宣言と代入 int a; a = 2; int a= 2; 二つの変数の宣言と代入 int a;int b; a = 1; b = 2; 変数の宣言における命名規則について
(Microsoftからの引用になります!)
フィールド名には Pascal 形式を使用してください。
フィールドの名前には、名詞や名詞句を使用してください。
フィールド名にはプリフィックスを使用しないでください。
たとえば、静的フィールドと非静的フィールドを区別するために、g_ や s_ を使用しないでください※Pascal形式とは!
・それぞれの単語の頭は大文字
・単語の間に「-(ハイフン)」や「_(アンダースコア)」は使わない変数の型
・値型と参照型がある
値型
・単純型
・列挙型
・構造体の型
・null許容値型
・ダブル値型
参照型
・クラス型
・インターフェイス型
・配列型
・デリゲート型※変数の型は別途記載したいと思う。
(各型について調べたが結構量が多い為、細かく分類します)参考資料
・Microsoft Build
・Wikipedia
・C#の絵本
- 投稿日:2020-05-31T19:47:48+09:00
初めてC#を学習する方へのおすすめサイト
数あるプログラミング言語。
初めての学習でC#を選んだけど、どうやって進めていくか迷っている方へおすすめのサイトをまとめました。初めてならば動画やシステムで学べるサイトが一番
私は初めての言語はC言語でした。
書籍を購入して、頭から順番に読み進めながら問題に挑戦するという、王道ともいうべき進め方でした。昨今ではWebサイトの充実により、書籍でなくても入門しやすくなっています。
HTML/CSS/JavaScript/Java/Goはすべてサイト学習しました。そんなサイト学習での定番サイトと言えば
が有名です。(Web関連の言語が多いです。)
C#はというと
となっています。
初めての言語学習で、いきなり有料会員登録というのも抵抗があるかと思います。そこで、C#の動画学習サイトとしては、paizaラーニングがおすすめです。
C#の初期学習はpaizaラーニングがおすすめ
paizaラーニングもドットインストール/Progateのように一部有料会員向けで構成される動画学習サイトですが、
C#は(2020/05/31現在)完全無料で公開されています。内容としては
- C#入門編1: プログラミングを学ぶ
- C#入門編2: 条件によって処理を変えてみよう
- C#入門編3: ループ処理を学ぶ
- C#入門編4: 配列の基礎
- C#入門編5: 多次元配列を理解しよう
- C#入門編6: メソッドを理解しよう
- C#入門編7: クラスを理解しよう
- C#入門編8: さらにクラスを理解しよう
- C#入門編9: Dictionaryの基礎
- C#入門編10: 例外処理を理解しよう
と、全10レッスンで構成され、各章6~11チャプターで構成されています。
全くプログラミングしたことない方でも入門できる難易度で構成されているのでおすすめです。C#以外で言語学習したことがある方は各レッスン/チャプターの演習問題だけトライすることで
誤答だったり、曖昧だった箇所のみ解説を聞くことでスムーズに学習できると思います。またpaizaラーニングではブラウザ上でコーディングできるので開発環境はいりません。
※PC上で環境を作りたい方は以下を参考にしてみてください。
Windows10+VSCode+.NET CoreでC#開発環境を作ろう!知識がついたら練習あるのみ
一通り知識がついたら、実際にプログラミングすることが上達にはかかせません。
その為には問題・回答がスムーズにできるサイトを利用するのがおすすめです。そのなかでもおすすめなのはプログラミングコンテストで有名なAtCoderの練習サイトであるAtCoder Problemsです。
数多くの問題を、こちらもサイト上でプログラミング・提出することができ、
正解・不正解をその場で確認できます。はじめはA問題:灰グレード、B問題:灰グレードを選んで挑戦すると良いでしょう。
基本である入力・出力を中心にアルゴリズムも学ぶことができます。AtCoderはC++における解説ページが多いですが、人気なため学習のたすけとなるサイトも多いので、詰まった時にも助けになるケースは多いです。
まとめ
今回は初学者向けのサイトを紹介しました。
C#はWindowsアプリケーションだけでなくMac/LinuxやCloudなどのバックエンドでも利用が増えている言語です。
是非、学習してみてください。
- 投稿日:2020-05-31T19:43:12+09:00
C# PEファイルの文字列リソースをすべて取得する
言語と動作確認環境
- C# 8、.NET Core 3.1 (Preview)
- Visual Studio Community 2019 Preview(Version 16.7.0 Preview 1.0)、Windows 10。
目的
C# 8と.NET Core 3.1でPEファイルの文字列リソースをすべて取得するサンプルコードです。同様のコードはQiitaや海外サイトでも公開されていますが、自身の学習のために作成しています。
サンプルコード
using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.InteropServices; namespace ConsoleApp1 { class Program { static void Main() { using var handle = NativeMethods.LoadLibraryExW( "user32.dll", IntPtr.Zero, NativeMethods.DONT_RESOLVE_DLL_REFERENCES | NativeMethods.LOAD_LIBRARY_AS_DATAFILE | NativeMethods.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); if (handle.IsInvalid) { throw new Win32Exception(); } var strings = GetStringResources(handle.DangerousGetHandle()); } /// <summary> /// ある型のリソースのIDをすべて取得します。 /// </summary> private static ushort[] GetResourceIDs(IntPtr moduleHandle, IntPtr resourceType) { var resnames = new List<ushort>(); NativeMethods.EnumResourceNamesW( moduleHandle, resourceType, (IntPtr hModule, IntPtr lpszType, IntPtr lpszName, nint lParam) => { var id = lpszName.ToInt64(); if (id >> 16 != 0) throw new Exception(); resnames.Add((ushort)id); return true; }, 0); return resnames.ToArray(); } /// <summary> /// モジュールの文字列リソースをすべて取得します。 /// </summary> private static string[] GetStringResources(IntPtr moduleHandle) { var stringResIds = GetResourceIDs(moduleHandle, NativeMethods.RT_STRING); Array.Sort(stringResIds); var strings = new List<string>(); foreach (var strResId in stringResIds) { var resHandle = NativeMethods.FindResourceW(moduleHandle, new IntPtr(strResId), NativeMethods.RT_STRING); var memoryHandle = NativeMethods.LoadResource(moduleHandle, resHandle); var size = NativeMethods.SizeofResource(moduleHandle, resHandle); // pointerの中身は2バイト(文字数N)+N*2バイト(UTF-16文字列)の配列 var pointer = NativeMethods.LockResource(memoryHandle); for (int offset = 0; offset < size;) { uint len = (ushort)Marshal.ReadInt16(pointer + offset); strings.Add(Marshal.PtrToStringUni(pointer + offset + sizeof(ushort), (int)len)); offset += sizeof(ushort) + (int)len * 2; } } return strings.ToArray(); } private static class NativeMethods { [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] public static extern SafeModuleHandle LoadLibraryExW( [In] string lpLibFileName, IntPtr hFile, uint dwFlags); [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumResourceNamesW( IntPtr hModule, IntPtr lpType, EnumResNameProcW lpEnumFunc, nint lParam); public const uint DONT_RESOLVE_DLL_REFERENCES = 0x00000001; public const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002; public const uint LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000; [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] public delegate bool EnumResNameProcW(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, nint lParam); public static readonly IntPtr RT_STRING = new IntPtr(6); [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] public static extern IntPtr FindResourceW( IntPtr hModule, IntPtr lpName, IntPtr lpType); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr LoadResource( IntPtr hModule, IntPtr hResInfo); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr LockResource( IntPtr hResData); [DllImport("kernel32.dll", SetLastError = true)] public static extern uint SizeofResource( IntPtr hModule, IntPtr hResInfo); } } public sealed class SafeModuleHandle : SafeHandle { private static class NativeMethods { [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FreeLibrary(IntPtr hLibModule); } public SafeModuleHandle() : base(IntPtr.Zero, true) { } public SafeModuleHandle(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle) { } public override bool IsInvalid => handle == IntPtr.Zero; protected override bool ReleaseHandle() { return NativeMethods.FreeLibrary(handle); } } }
HMODULE
型のSafeHandle
によるラップ
LoadLibraryEx
関数の戻り値はHMODULE
型のハンドルであり、使用後はFreeLibrary
関数で解放する必要があります。C#ではusing
構文とSafeHandle
の派生クラスにより確実な解放を保証できるため、ここではSafeHandle
を継承したクラスを作成しています。このハンドルを解放しなかった場合、プロセスの終了までライブラリがメモリ存在したままとなります。なお、同じ
HMODULE
型を返す関数でもGetModuleHandle
関数の戻り値は基本的に解放してはいけません。
LoadLibraryEx
関数とフラグ
LoadLobraryEx
関数の呼び出し時にはいくつかのフラグを指定することができます。今回は既定の場所からPEファイルを読み込み、そのリソースのみが必要なので以下のフラグを指定しています。
フラグ 目的 DONT_RESOLVE_DLL_REFERENCES DLL参照の解決を無効化する。 LOAD_LIBRARY_AS_DATAFILE データファイルとして読み込む。 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 既定の場所から検索する。
LoadResource
関数とLockResource
関数
LoadResource
関数とLockResource
関数は後方互換性のために別々に存在します。Windows 10ではどちらも同じ値を返します。戻り値はプロセスの終了時に自動的に解放されます(Microsoft Docs)。ポインタから整数や文字列の読み込み
System.Runtime.InteropServices
名前空間のMarshal
クラスを使用してポインタから整数や文字列を読み込むことができます。16ビット整数はMarshal.ReadInt16
、UTF-16文字列の読み込みはMarshal.PtrToStringUni
です。
RT_STRING
型リソースの中身
RT_STRING
型リソースは各IDに長さ(UInt16、2バイト)とその長さのUTF-16文字列(Char型)のペアが1~32個含まれます。各IDに含まれる文字列の個数は記録されていませんが、SizeofResource
関数で取得したバイト数まで上記ペアを読み込むことですべての文字列を取得できます。RT_STRING型リソースの模式図#ID 1 <- バイト数はSizeofResource関数で取得 Length(2バイト), String(Length文字 = Length*2バイト) ... Length(2バイト), String(Length文字 = Length*2バイト) <- 最大32個 #ID 2 Length(2バイト), String(Length文字 = Length*2バイト) ... Length(2バイト), String(Length文字 = Length*2バイト) ... #ID N <- EnumResourceNamesで見つかった個数だけ存在 ...
- 投稿日:2020-05-31T12:16:53+09:00
DICE#プログラム
この記事はC#のVisualStudio2019を使用しています。
実行の際には特に設定は必要ないです。
入力の必要はありません。このプログラムは1~4桁までのサイコロで合わせた数値で割り算を行い、割った出力した数値とその余りを求めるものになっています。
以下はそのソースコードです。
using System;
namespace Dice++++
{
class Program
{
static void Main(string[] args)
{
//1つ目のサイコロは一桁 0~9まで
var random = new Random();
var number = random.Next(0,10);
//2つ目のサイコロの二桁 0~9まで
var number2 = random.Next(0,10)*10;
//3つ目のサイコロの二桁 0~9まで
var number3 = random.Next(0, 10) * 100;
//4つ目のサイコロの二桁 1~9まで
var number4 = random.Next(1, 10) * 1000;//一桁、二桁、三桁と四桁のサイコロの数の合計 var number5 = number + number2 + number3 + number4 ; Console.WriteLine("1桁のサイコロの数は" + number +"、"); Console.WriteLine("2桁のサイコロの数は" + number2 + "、"); Console.WriteLine("3桁のサイコロの数は" + number3 + "、"); Console.WriteLine("4桁のサイコロの数は" + number4 + "、"); Console.WriteLine("4つのサイコロを足した数は" + number5 + "です"); double x = random.Next(1, 10) * 100; var X = number5 / x; double X1 = number5 % x; Console.WriteLine("合計を3桁の数字である"+x+"で割ると" + X + "になり、余りは"+ X1 +"になります"); } }}
出力例:
1回目
1桁のサイコロの数は8、
2桁のサイコロの数は20、
3桁のサイコロの数は200、
4桁のサイコロの数は6000、
4つのサイコロを足した数は6228です
合計を3桁の数字である600で割ると10.38になり、余りは228になります2回目
1桁のサイコロの数は2、
2桁のサイコロの数は60、
3桁のサイコロの数は700、
4桁のサイコロの数は1000、
4つのサイコロを足した数は1762です
合計を3桁の数字である900で割ると1.9577777777777778になり、余りは862になります以上です。
- 投稿日:2020-05-31T10:04:25+09:00
ASP.NET Core Web APIでソースコードからSwaggerUIを起動させる。ついでにインターフェース定義をJSON/YAMLで出力する。その定義ファイルからClientコードを自動生成する。
TL;DR
以下の手順で作られるコードを以下に置いておきます。お忙しい方はこちらからどうぞ
https://github.com/ishiyama0530/worksample-dotnetcore-swagger-axiosモチベーション
- ソースコードからOpenAPIのインターフェースを自動生成したい
- SwaggerUIを表示したい
- OpenAPIの定義ファイルをJSON/YAML形式で出力したい
- 定義ファイルからAxiosのコードを生成したい
- すべてを1コマンドで行いたい
参考
プロジェクト構成
最終的にはこんな感じになります。
$ tree ./worksample-dotnetcore-swagger-axios -a -L 1 ./worksample-dotnetcore-swagger-axios ├── .config ├── .git ├── .gitignore ├── ClientApp ├── Controllers ├── Pages ├── Program.cs ├── Properties ├── Startup.cs ├── WeatherForecast.cs ├── appsettings.Development.json ├── appsettings.json ├── bin ├── node_modules ├── obj ├── openapi.json ├── openapi.yml ├── package-lock.json ├── package.json ├── scripts ├── worksample-dotnetcore-swagger-axios.csproj └── wwwrootプロジェクト作成
vueでもreactでもangularでも何でもいいですが、とりあえずテンプレートが用意されているreactで進めます。
mkdir worksample-dotnetcore-swagger-axios dotnet new reactredux -o worksample-dotnetcore-swagger-axios cd worksample-dotnetcore-swagger-axios dotnet run // localhost:5001でhelloworldが表示されますSwaggerUIを表示するまで
パッケージ
dotnet add package Swashbuckle.AspNetCore --version 5.4.1
Controller
SampleController.csを作成します。
worksample-dotnetcore-swagger-axios/Controllers/SampleController.csusing System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Mvc; namespace worksample_dotnetcore_swagger_axios.Controllers { [ApiController] [Route("[controller]")] public class SampleController : ControllerBase { /// <summary> /// ほげほげ /// </summary> /// <param name="model">ふがふが</param> /// <returns>ほげほげふがふが</returns> [HttpPost("{id}")] public ResponseModel Post([Required][FromBody]RequestModel model) { return new ResponseModel(); } } public class RequestModel{ [Required] public string Param { get; set; } } public class ResponseModel{ [Required] public string Value { get; set; } } }Startup::ConfigureServices
サービスを追加します。
worksample-dotnetcore-swagger-axios/Startup.csservices.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); // operationidの設定 c.CustomOperationIds(e => $"{e.ActionDescriptor.RouteValues["controller"]}{e.ActionDescriptor.RouteValues["action"]}"); // コメントも定義に出力するように var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); });Startup::Configure
ミドルウェアは定義する順番によって動作が変わります。
今回はとりあえずConfigureメソッドの一番上に追加します。worksample-dotnetcore-swagger-axios/Startup.csapp.UseStaticFiles(); // for wwwroot/swagger/ui app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); });プロジェクトファイル
XMLコメントを有効にするためにプロジェクトファイルに以下を追加します。
bin以下にコメントのxmlファイルを出力するようになります。worksample-dotnetcore-swagger-axios/worksample-dotnetcore-swagger-axios.csproj<PropertyGroup> <GenerateDocumentationFile>true</GenerateDocumentationFile> <NoWarn>$(NoWarn);1591</NoWarn> </PropertyGroup>起動
dotnet runhttps://localhost:5001/swagger/v1/swagger.json
上記URLにアクセスするとOpenAPIのインターフェース定義を確認できます。Swagger UIの準備
プロジェクト直下に
wwwroot/swagger/ui
ディレクトリ作成し、GitHub SwaggerUIのdistフォルダの中身をまるっとコピーします。$ tree ./wwwroot/ ./wwwroot/ └── swagger └── ui ├── favicon-16x16.png ├── favicon-32x32.png ├── index.html ├── oauth2-redirect.html ├── swagger-ui-bundle.js ├── swagger-ui-bundle.js.map ├── swagger-ui-standalone-preset.js ├── swagger-ui-standalone-preset.js.map ├── swagger-ui.css ├── swagger-ui.css.map ├── swagger-ui.js └── swagger-ui.js.map
wwwroot/swagger/ui/index.html
の42行目あたりの読み込む定義ファイルのURLを、自分の定義に修正します。worksample-dotnetcore-swagger-axios/wwwroot/swagger/ui/index.htmlconst ui = SwaggerUIBundle({ // url: "https://petstore.swagger.io/v2/swagger.json", url: "https://localhost:5001/swagger/v1/swagger.json", dom_id: '#swagger-ui', 省略...起動
dotnet runhttps://localhost:5001/swagger/ui/index.html
上記URLにアクセスするとSwaggerUIを確認できます。インターフェース定義をJSON/YAMLで出力するまで
パッケージ
dotnet add package Swashbuckle.AspNetCore.Newtonsoft --version 5.4.1 dotnet add package Swashbuckle.AspNetCore.Swagger --version 5.4.1dotnet-tools.json
プロジェクト直下に.configフォルダを作り、その下にdotnet-tools.jsonを作成します。
worksample-dotnetcore-swagger-axios/.config/dotnet-tools.json{ "version": 1, "isRoot": true, "tools": { "swashbuckle.aspnetcore.cli": { "version": "5.4.1", "commands": [ "swagger" ] } } }プロジェクトファイル
今回はビルド後に指定したパスに定義ファイルを自動で出力するようにします。
ビルド後イベントにHookするためにプロジェクトファイルに以下を追加します。worksample-dotnetcore-swagger-axios/worksample-dotnetcore-swagger-axios.csproj<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Exec Command="dotnet tool restore" /> <Exec Command="dotnet swagger tofile --output ./openapi.json ./bin/Debug/netcoreapp3.1/worksample-dotnetcore-swagger-axios.dll v1" /> <Exec Command="dotnet swagger tofile --yaml --output ./openapi.yml ./bin/Debug/netcoreapp3.1/worksample-dotnetcore-swagger-axios.dll v1" /> </Target>ビルド
.NET Core 2.1 Runtime が入っていない環境だとビルドが通らないようです。
私は以下からダウンロードしました。Download .NET Core 2.1
https://dotnet.microsoft.com/download/dotnet-core/2.1dotnet buildプロジェクト直下に以下のファイルが出力されていれば成功です。
- openapi.json
- openapi.yml
インターフェース定義ファイルからAxiosのコードを生成するまで
パッケージ
Axios本体とインターフェース定義ファイルからAxiosのコードを生成してくれる
openapi-generator-cli
をインストールします。cd ClientApp/ npm install axios npm install -D @openapitools/openapi-generator-cli生成前にディレクトリを削除したいので
rimraf
もインストールしますnpm install -D rimrafnpm-scripts
./ClientApp/package.json
に以下を追加します。worksample-dotnetcore-swagger-axios/ClientApp/package.json"scripts": { ...省略 "openapi:regen": "rimraf ./src/openapisdk && openapi-generator generate -g typescript-axios -i ../openapi.json -o ./src/openapisdk" }上記のスクリプトを実行するとプロジェクト直下にある
openapi.json
をもとに./ClientApp/src/openapisdk
にAxiosのコードが生成されます。npm run openapi:regendotnetビルド→openapi:regenを1コマンドで
方法はいろいろあると思いますが、クロスプラットフォームに対応したいのでnpm-scriptsに書いていきます。
プロジェクト直下にpackage.jsonを作ります。
cd ../ npm init
npm-scriptsからdotnetコマンドを実行したいのでshelljsをインストールします。
npm i shelljsプロジェクト直下にscriptsフォルダを作りその下にdotnetbuild.jsを作りました。
worksample-dotnetcore-swagger-axios/scripts/dotnetbuild.jsvar shell = require('shelljs'); if (shell.exec("dotnet build").code !== 0) { shell.exit(1); }最後にnpm-scriptsに以下を記述します。
worksample-dotnetcore-swagger-axios/package.json"scripts": { "openapi:clientapp": "node ./scripts/dotnetbuild.js && cd ./ClientApp && npm run openapi:regen" }これでプロジェクトのビルドからAxiosのコード生成が1コマンドで行われるようになりました。
npm run openapi:clientappおまけ
Swagger UIのテーマはこちらからどうぞ
Swagger UI Themes
https://ostranme.github.io/swagger-ui-themes/
- 投稿日:2020-05-31T10:04:25+09:00
ASP.NET Coreとフロントエンドの繋ぎこみをOpenAPI(Swagger)定義ファイルを使って効率化する
TL;DR
以下の手順で作られるコードを以下に置いておきます。お忙しい方はこちらからどうぞ
https://github.com/ishiyama0530/worksample-dotnetcore-swagger-axiosモチベーション
- ソースコードからOpenAPIのインターフェースを生成したい
- SwaggerUIを表示したい
- OpenAPIの定義ファイルをJSON/YAML形式で出力したい
- 定義ファイルからAxiosのコードを生成したい
- すべてを1コマンドで行いたい
参考
プロジェクト構成
最終的にはこんな感じになります。
$ tree ./worksample-dotnetcore-swagger-axios -a -L 1 ./worksample-dotnetcore-swagger-axios ├── .config ├── .git ├── .gitignore ├── ClientApp ├── Controllers ├── Pages ├── Program.cs ├── Properties ├── Startup.cs ├── WeatherForecast.cs ├── appsettings.Development.json ├── appsettings.json ├── bin ├── node_modules ├── obj ├── openapi.json ├── openapi.yml ├── package-lock.json ├── package.json ├── scripts ├── worksample-dotnetcore-swagger-axios.csproj └── wwwrootプロジェクト作成
vueでもreactでもangularでも何でもいいですが、とりあえずテンプレートが用意されているreactで進めます。
mkdir worksample-dotnetcore-swagger-axios dotnet new reactredux -o worksample-dotnetcore-swagger-axios cd worksample-dotnetcore-swagger-axios dotnet run // localhost:5001でhelloworldが表示されますSwaggerUIを表示するまで
パッケージ
dotnet add package Swashbuckle.AspNetCore --version 5.4.1
Controller
SampleController.csを作成します。
worksample-dotnetcore-swagger-axios/Controllers/SampleController.csusing System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Mvc; namespace worksample_dotnetcore_swagger_axios.Controllers { [ApiController] [Route("[controller]")] public class SampleController : ControllerBase { /// <summary> /// ほげほげ /// </summary> /// <param name="model">ふがふが</param> /// <returns>ほげほげふがふが</returns> [HttpPost("{id}")] public ResponseModel Post([Required][FromBody]RequestModel model) { return new ResponseModel(); } } public class RequestModel{ [Required] public string Param { get; set; } } public class ResponseModel{ [Required] public string Value { get; set; } } }Startup::ConfigureServices
サービスを追加します。
worksample-dotnetcore-swagger-axios/Startup.csservices.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); // operationidの設定 c.CustomOperationIds(e => $"{e.ActionDescriptor.RouteValues["controller"]}{e.ActionDescriptor.RouteValues["action"]}"); // コメントも定義に出力するように var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); });Startup::Configure
ミドルウェアは定義する順番によって動作が変わります。
今回はとりあえずConfigureメソッドの一番上に追加します。worksample-dotnetcore-swagger-axios/Startup.csapp.UseStaticFiles(); // for wwwroot/swagger/ui app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); });プロジェクトファイル
XMLコメントを有効にするためにプロジェクトファイルに以下を追加します。
bin以下にコメントのxmlファイルを出力するようになります。worksample-dotnetcore-swagger-axios/worksample-dotnetcore-swagger-axios.csproj<PropertyGroup> <GenerateDocumentationFile>true</GenerateDocumentationFile> <NoWarn>$(NoWarn);1591</NoWarn> </PropertyGroup>起動
dotnet runhttps://localhost:5001/swagger/v1/swagger.json
上記URLにアクセスするとOpenAPIのインターフェース定義を確認できます。Swagger UIの準備
プロジェクト直下に
wwwroot/swagger/ui
ディレクトリ作成し、GitHub SwaggerUIのdistフォルダの中身をまるっとコピーします。$ tree ./wwwroot/ ./wwwroot/ └── swagger └── ui ├── favicon-16x16.png ├── favicon-32x32.png ├── index.html ├── oauth2-redirect.html ├── swagger-ui-bundle.js ├── swagger-ui-bundle.js.map ├── swagger-ui-standalone-preset.js ├── swagger-ui-standalone-preset.js.map ├── swagger-ui.css ├── swagger-ui.css.map ├── swagger-ui.js └── swagger-ui.js.map
wwwroot/swagger/ui/index.html
の42行目あたりの読み込む定義ファイルのURLを、自分の定義に修正します。worksample-dotnetcore-swagger-axios/wwwroot/swagger/ui/index.htmlconst ui = SwaggerUIBundle({ // url: "https://petstore.swagger.io/v2/swagger.json", url: "https://localhost:5001/swagger/v1/swagger.json", dom_id: '#swagger-ui', 省略...起動
dotnet runhttps://localhost:5001/swagger/ui/index.html
上記URLにアクセスするとSwaggerUIを確認できます。インターフェース定義をJSON/YAMLで出力するまで
パッケージ
dotnet add package Swashbuckle.AspNetCore.Newtonsoft --version 5.4.1 dotnet add package Swashbuckle.AspNetCore.Swagger --version 5.4.1dotnet-tools.json
プロジェクト直下に.configフォルダを作り、その下にdotnet-tools.jsonを作成します。
worksample-dotnetcore-swagger-axios/.config/dotnet-tools.json{ "version": 1, "isRoot": true, "tools": { "swashbuckle.aspnetcore.cli": { "version": "5.4.1", "commands": [ "swagger" ] } } }プロジェクトファイル
今回はビルド後に指定したパスに定義ファイルを自動で出力するようにします。
ビルド後イベントにHookするためにプロジェクトファイルに以下を追加します。worksample-dotnetcore-swagger-axios/worksample-dotnetcore-swagger-axios.csproj<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Exec Command="dotnet tool restore" /> <Exec Command="dotnet swagger tofile --output ./openapi.json ./bin/Debug/netcoreapp3.1/worksample-dotnetcore-swagger-axios.dll v1" /> <Exec Command="dotnet swagger tofile --yaml --output ./openapi.yml ./bin/Debug/netcoreapp3.1/worksample-dotnetcore-swagger-axios.dll v1" /> </Target>ビルド
.NET Core 2.1 Runtime が入っていない環境だとビルドが通らないようです。
私は以下からダウンロードしました。Download .NET Core 2.1
https://dotnet.microsoft.com/download/dotnet-core/2.1dotnet buildプロジェクト直下に以下のファイルが出力されていれば成功です。
- openapi.json
- openapi.yml
インターフェース定義ファイルからAxiosのコードを生成するまで
パッケージ
Axios本体とインターフェース定義ファイルからAxiosのコードを生成してくれる
openapi-generator-cli
をインストールします。cd ClientApp/ npm install axios npm install -D @openapitools/openapi-generator-cli生成前にディレクトリを削除したいので
rimraf
もインストールしますnpm install -D rimrafnpm-scripts
./ClientApp/package.json
に以下を追加します。worksample-dotnetcore-swagger-axios/ClientApp/package.json"scripts": { ...省略 "openapi:regen": "rimraf ./src/openapisdk && openapi-generator generate -g typescript-axios -i ../openapi.json -o ./src/openapisdk" }上記のスクリプトを実行するとプロジェクト直下にある
openapi.json
をもとに./ClientApp/src/openapisdk
にAxiosのコードが生成されます。npm run openapi:regendotnetビルド→openapi:regenを1コマンドで
方法はいろいろあると思いますが、クロスプラットフォームに対応したいのでnpm-scriptsに書いていきます。
プロジェクト直下にpackage.jsonを作ります。
cd ../ npm init
npm-scriptsからdotnetコマンドを実行したいのでshelljsをインストールします。
npm i shelljsプロジェクト直下にscriptsフォルダを作りその下にdotnetbuild.jsを作りました。
worksample-dotnetcore-swagger-axios/scripts/dotnetbuild.jsvar shell = require('shelljs'); if (shell.exec("dotnet build").code !== 0) { shell.exit(1); }最後にnpm-scriptsに以下を記述します。
worksample-dotnetcore-swagger-axios/package.json"scripts": { "openapi:clientapp": "node ./scripts/dotnetbuild.js && cd ./ClientApp && npm run openapi:regen" }これでプロジェクトのビルドからAxiosのコード生成が1コマンドで行われるようになりました。
npm run openapi:clientappおまけ
Swagger UIのテーマはこちらからどうぞ
Swagger UI Themes
https://ostranme.github.io/swagger-ui-themes/
- 投稿日:2020-05-31T09:47:11+09:00
BlazorでFluxorを使った状態管理
(An English version of this article is also available.)
この記事ではBlazorで状態管理(State Management)を行う手法について紹介していきます。
今回使用したのはFluxorという.NET向けのFlux/Redux実装です。状態管理とは
状態管理、State Managementとは多くのコンポーネントに散らばりがちなアプリケーション内の状態を集約する形でアプリケーションの状態変化(ユーザーの入力等)に柔軟に対応できるようなシステムです。
使用したプロジェクト
今回使用したプロジェクトは拙作の仙狐ビュワーです。完全なソースは公開していませんが、仕組み自体はシンプルなプロジェクトですので、コードサンプルを交え、その実装の仕組みについて紹介していきます。
プロジェクトの内容
仙狐ビュワーは高解像度の画像を公開するためのシステムで、要はスライドショーアプリケーションです。URLからのパラメーターの受け取りや自動ページ切り替えなどの機能も実装していますが、今回の状態管理とはあまり関係していませんので、説明は省きます。
仙狐ビュワーでは画像情報を示したJSONファイルを読み取り、そのJSONファイルを元にインデックスを作成、それを目次として使い、画像を読み込む、という仕組みになっています。
以前の実装
以前使用していたシンプルな実装においてはただ単に、インデックスを保持し、ボタンの押下に対してそのインデックスを書き換える方法でした。この手のプログラムにおいては教科書的なかなりシンプルな実装です。
<div> <img src="@imageName"/> </div> @code { public string imageName; List<SenkoImage> images private int index = 0; public class SenkoImage { public string FileLocation; public string FileId; } public void Next() { index++; // ... 最後のページに達した場合の処理(0に戻す) imageName = images[index].FileLocation; } public void Prev() { index--; // ... 最初のページに達した場合の処理(最大ページに戻す) imageName = images[index].FileLocation; } public void Set(int index) { // ... indexが正常値かどうかを確認 imageName = images[index].FileLocation; } protected override async Task OnAfterRenderAsync(bool firstRender) { // リストの初期化など } }実際はこの程度の実装であればこのような形で行うのも全く問題ないかと思います。ただ、ここでは状態管理の実装を試してみる、というモチベーションがありますので、敢えて、これを状態管理の手法で実装してみます。
Fluxorを導入
早速Fluxorを導入していきます。
尚、Fluxorは状態管理そのものを実装しているシステムであり、必ずしもBlazorと合わせて使う必要がありません。実際にコマンドラインアプリでこれを使う方法も紹介されています。
今回はBlazorアプリで使用しますので、Fluxor.Blazor.Web
パッケージをプロジェクトに追加して下さい。執筆時点でのバージョンは3.1.1です。有効化の方法
有効化に必要なコードはドキュメントでも紹介されていますが、概ね以下のとおりです。(他のライブラリで使用される方法とあまり違いはありません。)
www/index.html
(Blazor Serverの場合Pages/_Host.cshtml
)に以下を追加。<script src="_content/Fluxor.Blazor.Web/scripts/index.js"></script>
Program.Main
メソッドに以下を追加。var currentAssembly = typeof(Program).Assembly; builder.Services.AddFluxor(options => options.ScanAssemblies(currentAssembly));Blazor Serverの場合は次を
Startup.ConfigureServices
メソッドに追加します。var currentAssembly = typeof(Startup).Assembly; services.AddFluxor(options => options.ScanAssemblies(currentAssembly));
App.razor
に以下を追加。<Fluxor.Blazor.Web.StoreInitializer/>実装
ここから実装していきます。
状態の定義
先ずは状態の定義を行います。今回の例では単一のシンプルなルールですので
Store/SlideUseCase/SlideState.cs
を作成し、以下のように定義しました。namespace SenkoViewer.Store.SlideUseCase { public class SlideState { public SlideState(int slideCount) { SlideCount = slideCount; } public int SlideCount { get; } } }これが状態を格納するためのクラスになります。
次に、Featureを定義します。こちらは
Store/SlideUseCase/Feature.cs
として作成しました。using Fluxor; namespace SenkoViewer.Store.SlideUseCase { public class Feature : Feature<SlideState> { public override string GetName() { return "Slide"; } protected override SlideState GetInitialState() { return new SlideState(0); } } }状態変移の実装
ここで各機能を実装していきますが、今回の例では大きく三種類の機能を持たせます。以下のとおりです。
- 次のページに移行する
IncrementSlide
- 前のページに移行する
DecrementSlide
- 任意のページに移行する
SetSlide
まずは
IncrementSlide
を実装します。DecrementSlide
に関してはこれと同様ですが、インデックスを減らす処理になります。
Store/SlideUseCase/IncrementSlideAction.cs
に以下のようにしました。こちらは空で問題ありません。namespace SenkoViewer.Store.SlideUseCase { public class IncrementSlideAction { } }次に
Store/SlideUseCase/Reducers.cs
に以下のように記述します。using Fluxor; namespace SenkoViewer.Store.SlideUseCase { public class Reducers { [ReducerMethod] public static SlideState ReduceIncrementSlideAction(SlideState state, IncrementSlideAction action) { return new SlideState(state.SlideCount + 1); } } }表示ロジックからの使用
さて、これを使用するためにはロジックから使用することにします。仙狐ビュワーにおいては、まず、画像表示部を専用のコンポーネントに移動させ、以下のような形で画像を呼び出せる形にしました。
<SenkoDisplay Index="0"/>ですので、razorファイルの中では以下のように定義されています。これにより、画像のインデックスは状態管理のものが読み出されます。
<SenkoDisplay Index="@SlideState.Value.SlideCount"/>まず、使用するrazorファイルに以下を追加します。
@inherits Fluxor.Blazor.Web.Components.FluxorComponentその上でDispatcherをインジェクトします。
[Inject] public IDispatcher Dispatcher { get; set; }また、各状態ごとにインターフェースもインジェクトします。
[Inject] private IState<SlideState> SlideState { get; set; }次に進めるためのメソッドは以下のようにします。
public async Task Next() { var action = new IncrementSlideAction(); Dispatcher.Dispatch(action); await InvokeAsync(StateHasChanged); }これでこのメソッドが呼び出されると次の画像が表示される形になります。
任意の画像を設定できるようにする
仙狐ビュワーの機能として、パラメーターから提示した識別子(画像のハッシュ値)をもとに画像を呼び出したり、また、ランダムに画像を表示する機能も含んでいます。そのため、現在の形ではそれが行なえません。
そのため、
SetSlide
として、これを行うためのものを実装していきます。
Store/SlideUseCase/SetSlideAction.cs
はIncrementやDecrementのものと少し違うものになります。(これはIncrementやDecrementでは空の実装だったものです。)namespace SenkoViewer.Store.SlideUseCase { public class SetSlideAction { public SetSlideAction(int index) { Value = index; } public int Value { get; set; } } }これにより、アクションに
Value
を渡せるようにします。Reducerに関してはこれから取り出した値を設定する形になります。
[ReducerMethod] public static SlideState ReduceSetSlideAction(SlideState state, SetSlideAction action) { return new SlideState(action.Value); }これにより、以下のような形で任意の画像を表示できるようになります。
var action = new SetSlideAction(5); Dispatcher.Dispatch(action);ページのループを設定する
現在の実装のままでは最後のページに次、最初のページに前に進むような形になった場合に、例外が発生してしまいます。
そのため、
Store/SlideUseCase/SlideState.cs
を次のように変更してみます。using SenkoViewer.AssetAccessor; namespace SenkoViewer.Store.SlideUseCase { public class SlideState { public SlideState(int slideCount) { if (slideCount > Max - 1) SlideCount = 0; else if (slideCount < 0) SlideCount = Max - 1; else SlideCount = slideCount; } public int SlideCount { get; } } }最後に
仙狐ビュワーの場合には機能がさほど複雑ではないところもあり、これを行うことで却ってコード量が反対に増えてしまう形になります。より複雑な状態を管理しないといけない場合において、状態管理はその威力を発揮するかと思います。
Fluxor自体はBlazorアプリ以外でも使用できるようになっている点など、他にも応用することができ、ソリューションを問わず、状態管理機構が必要な場合において有用かと思います。
Fluxorにはこの他、Effectorなど他の使用ケースなども使用することが出来ますが、これはまたの機会に紹介していきたいと思います。
- 投稿日:2020-05-31T09:20:43+09:00
JsonからC#のクラスモデルの作成
C#でJsonをパースする際にクラスモデルを作成すると楽なのですが、
この時にJsonからC#のクラスへ変換してくれるサイトがあります。よく出てくるのは
http://json2csharp.com/
なのですが、どうも今は閉まっているみたいです。代わりを探してみたら以下のサイトが使えました。
https://jsonutils.com/
- 投稿日:2020-05-31T02:48:30+09:00
OpenCVSharpでマウスを使う
概要
ちょっとした操作をマウスで行いたかった。さらに線や円などのプリミティブな図形も描きたかったので、OpenCVSharpを使ってみることにした。そこで引っ掛かったことを記す。
不具合例
Program.csusing OpenCvSharp; class Program { public static Mat img; static Point mousepos = new Point(); static Scalar color = new Scalar(0, 255, 255); static void Main(string[] args) { img = new Mat(new Size(640, 480), MatType.CV_8UC3); using (Window win = new Window("OpenCV", img)) { Cv2.SetMouseCallback("OpenCV", Win_OnMouseCallback); while(true) { Cv2.ImShow("OpenCV", img); int ret = Cv2.WaitKey(1); if (ret == 27) { break; } } Cv2.DestroyAllWindows(); } }//End of Main private static void Win_OnMouseCallback(MouseEventTypes @event, int x, int y, MouseEventFlags flags, IntPtr userdata) { Console.WriteLine($"event: {@event}, (x, y)= ({x}, {y}), flags: {flags}"); if (flags==MouseEventFlags.LButton) { mousepos.X = x; mousepos.Y = y; img.Circle(mousepos, 2, color); } } }何の変哲もない。
しかしリリースモードでビルドして実行して、暫くすると
これは何のことだろう?デバッグモードでは出てこないけど・・・
ググると、C#のリリースモードはいろいろ最適化されてるから別コードと考えた方がよいとか、Releaseでもデバッグ用にログを取るとかいろいろ出てきた。でもこんな簡単なものなのに・・
しかもアンマネージってOpenCVのところ??解決策
ようやく探し出せた
https://www.ipentec.com/document/csharp-error-delegate-must-be-kept-alive-by-the-managed-application
よく見るとWin_MouseCallBackはdelegate型になってない。staticで宣言されているけど、ガベージコレクタが回収してしまうようだ。ちゃんと確保して回収されないようにしてあげよう。差分だけ書かせてもらうと正しくはProgram.cspublic static Mat img; static Point mousepos = new Point(); static Scalar color = new Scalar(0, 255, 255); static MouseCallback mcb; //追加 static void Main(string[] args) { img = new Mat(new Size(640, 480), MatType.CV_8UC3); mcb=new MouseCallback(Win_OnMouseCallback); //追加 using (Window win = new Window("OpenCV", img)) { Cv2.SetMouseCallback("OpenCV", mcb);//変更 while(true) //以下略この「ガベージコレクタが回収する」エラーは、IDEでデバッグしているときは出てこず、使い始めてしばらくすると出てくるのと、再現するのに時間がかかるので、だいぶ厄介だった。わかってみれば「型を合わせてメモリを確保する」をちゃんとするだけなのだが。C++のDLLを使うプログラムでは気を付けよう。
- 投稿日:2020-05-31T01:19:33+09:00
C# Linqを使ったら超便利だった#1
Linqとは
C#の統合言語型クエリ
コレクションの要素を処理するメソッドがある。Linqを使用するとfor文やforeach文、if文を使用しなくても
処理を書くことが出来る場合があります。
そのため、全体のライン数とネストを減らして記載することが出来ます。
ライン数やネストが減ると可読性向上にも繋がります。Linqを使用したと使用しない処理での違いを検証
今回はそれぞれの動作を確認しつつ、Listに格納したデータを処理してみます。
以下に記載しているサンプルソースは以下のリストを宣言しており、以下の宣言はサンプルソースから省いています。sample.csList<int> source = new List<int>() { 1, 2, 3, 4, 5, 6 }; List<int> target = new List<int>();また、foreachはListクラスのForEachメソッドを使用して、以下のように書き換えています。
sample.csforeach(int num in source) { Console.WriteLine(num); }sample.cssource.ForEach(delegate (int num) { Console.WriteLine(num); });
- Where
WhereはList内から条件に一致したデータを抽出します。
Linqを使わない場合
sample.csforeach (int num in source) { //sourceから5未満のリストを作成 if(num < 5) { target.Add(num); } } //sourceを出力 Console.WriteLine("source"); foreach (int num in source) { Console.WriteLine(num); } //targetを出力 Console.WriteLine("target"); foreach (int num in target) { Console.WriteLine(num); }Linqを使った場合
sample.cs//sourceから5未満のリストを作成 target = source.Where(num => num < 5).ToList(); //sourceを出力 Console.WriteLine("source"); source.ForEach(delegate (int num) { Console.WriteLine(num); }); //targetを出力 Console.WriteLine("target"); target.ForEach(delegate (int num) { Console.WriteLine(num); });
- Select
SelectはList内の要素を計算した結果を出力できます。
リストの値にLinqを使わない場合
sample.csList<int> source = new List<int>() { 1, 2, 3, 4, 5, 6 }; List<int> target = new List<int>(); foreach (int num in source) { //5を乗算した値を追加 target.Add(num * 5); } foreach (int num in target) { Console.WriteLine(num); }Linqを使った場合
sample.cstarget = source.Select(num => num * 5).ToList(); target.ForEach(delegate (int num) {Console.WriteLine(num); });Selectでは以下のようにして、インデックスを抜き出すこともできます。
sample.cssource.Select((data, index) => new { Data = data, Index = index })
- その他の便利な使い方
foreachとwhichを組み合わせるとforeachの中でif文を記載しなくても、同様の処理が出来たりします。
リストの値を出力する処理です。sample.csforeach (int data in source.Where(tmpData => (tmpData == 1) || (tmpData == 3))) { Console.WriteLine(data); }組み合わせると以下のような処理もできたりします。
0番目から偶数位置に格納されているリストの値を出力する処理です。
ここまですると逆に複雑な気もします。sample.cssource.Select((data, index) => new { Data = data, Index = index }) .Where(SelectData => (SelectData.Index == 0 || SelectData.Index % 2 == 0)).ToList() .ForEach(num => { Console.WriteLine(num.Data); });
- 終わりに
Linqのメソッドを紹介してみました。
Linqはぱっと見でわかりにくい場合もあるので、なるべくコメントは書いた方がよさそうですね
他にもLinqの便利なメソッドはあるので、また時間があるときに書きます。
- 投稿日:2020-05-31T00:16:26+09:00
[C#] Entity Framework Coreのデータベースファーストでエラーが出た時の対処方法
エラー内容
PM> Scaffold-DbContext "[ConnectionString]" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Entities Build started... Build succeeded. Error: An assembly specified in the application dependencies manifest (project_name.deps.json) was not found: package: 'project_name', version: '1.0.0' path: 'project_name.dll'対処方法
dotnet ef dbcontext scaffold "[ConnectionString]" Microsoft.EntityFrameworkCore.SqlServer -o Entities補足
以下は必須。
dotnet tool install --global dotnet-ef dotnet add package Microsoft.EntityFrameworkCore.Design参考資料