- 投稿日:2020-04-09T19:29:50+09:00
お手軽Linux Guiアプリ開発 初級 前編
お手軽Linux Guiアプリ開発 初級 前編
- Sqlite3の利用
- Dapperの導入 Dapperについてまとめてみた
- Dapper Extensionの導入 Dapperの拡張ライブラリ 比較検討
- Swaggerを使う Stoplight Studioなどを使う 本当に使ってよかったOpenAPI (Swagger) ツール
- C#からPythonを実行する C#からPythonスクリプトを呼び出す
- DataGrideViewとModelのバインディングの実現 URL treeView
- RazurebyPiへのデプロイの仕方
前編は5まで
プロジェクトはGtk#を選択する
Nugetからパッケージをダウンロードする
ダウンロードするパッケージ
Dapper
DapperExtensions
Mono.Data.Sqliteをダウンロードします。Gtk2#の場合はSystem.Data.Sqliteは読み込めません。Dapperを使ったQuery
Queryの結果を自動でモデルに入れることができます。またInsert時Update時に引数代わりにModelを使えます。
static public void _dapperTest() { Mono.Data.Sqlite.SqliteConnection connection = new Mono.Data.Sqlite.SqliteConnection(); connection.ConnectionString = @"Data Source=パス/test.sqlite"; connection.Open(); var qurey = "select * from testTable;"; var result = connection.Query<testTable>(qurey); foreach(var p in result) { Console.WriteLine("ID:" + p.test_id + " 名称:" + p.name); } connection.Close(); }DapperExtensionを使ったInsertUpdate処理
ModelからInsert文やUpdate文を自動生成し、処理できます
Sql文を生成を変更します
DapperExtensions.DapperExtensions.SqlDialect = new DapperExtensions.Sql.SqliteDialect();static public void _dapperExtensionTest() { //Sql文を [testTable].[test_id]から [test_id]に変更する DapperExtensions.DapperExtensions.SqlDialect = new DapperExtensions.Sql.SqliteDialect(); Mono.Data.Sqlite.SqliteConnection connection = new Mono.Data.Sqlite.SqliteConnection(); connection.ConnectionString = @"Data Source=パス/test.sqlite"; connection.Open(); //DapperExtensionを使った処理 testTable testTable1 = new testTable(); testTable1.name = "aaaaaa111"; connection.Insert<testTable>(testTable1); var qurey = "select * from testTable;"; var result = connection.QueryFirst<testTable>(qurey); //DapperExtensionを使った処理 result.name += "qqqq111"; connection.Update<testTable>(result); connection.Close(); }Swaggerを自動生成にさせる
SpotlitStudioを使います。
本当に使ってよかったOpenAPI (Swagger) ツール
開発にあたってのポイント
- Gtk2#はMono.Data.Sqliteを使う。Dapperと併用できた
- gtkのサンプルを探すのに苦労した。C# gtk hotexamples 調べたいメソッド名で調べるとgitに上がっているサンプルを一覧できるサイトが見つけることができた。
- モデルにDataMemerを追加し、Dbのカラム名と変数名を紐づける(マッピング)
後編に続く
- 投稿日:2020-04-09T19:29:50+09:00
お手軽Linux GUIアプリ開発 初級 前編
お手軽Linux GUIアプリ開発 初級 前編
- Sqlite3の利用
- Dapperの導入 Dapperについてまとめてみた
- Dapper Extensionの導入 Dapperの拡張ライブラリ 比較検討
- Swaggerを使う Stoplight Studioなどを使う 本当に使ってよかったOpenAPI (Swagger) ツール
- C#からPythonを実行する C#からPythonスクリプトを呼び出す
- DataGridViewとModelのバインディングの実現 URL treeView
- RaspberryPiへのデプロイの仕方
前編は5まで
プロジェクトはGtk#を選択する
Nugetからパッケージをダウンロードする
ダウンロードするパッケージ
Dapper
DapperExtensions
Mono.Data.Sqliteをダウンロードします。Gtk2#の場合はSystem.Data.Sqliteは読み込めません。Dapperを使ったQuery
Queryの結果を自動でモデルに入れることができます。またInsert時Update時に引数代わりにModelを使えます。
static public void _dapperTest() { Mono.Data.Sqlite.SqliteConnection connection = new Mono.Data.Sqlite.SqliteConnection(); connection.ConnectionString = @"Data Source=パス/test.sqlite"; connection.Open(); var query = "select * from testTable;"; var result = connection.Query<testTable>(query); foreach(var p in result) { Console.WriteLine("ID:" + p.test_id + " 名称:" + p.name); } connection.Close(); }DapperExtensionを使ったInsertUpdate処理
ModelからInsert文やUpdate文を自動生成し、処理できます
Sql文を生成を変更します
DapperExtensions.DapperExtensions.SqlDialect = new DapperExtensions.Sql.SqliteDialect();static public void _dapperExtensionTest() { //Sql文を [testTable].[test_id]から [test_id]に変更する DapperExtensions.DapperExtensions.SqlDialect = new DapperExtensions.Sql.SqliteDialect(); Mono.Data.Sqlite.SqliteConnection connection = new Mono.Data.Sqlite.SqliteConnection(); connection.ConnectionString = @"Data Source=パス/test.sqlite"; connection.Open(); //DapperExtensionを使った処理 testTable testTable1 = new testTable(); testTable1.name = "aaaaaa111"; connection.Insert<testTable>(testTable1); var query = "select * from testTable;"; var result = connection.QueryFirst<testTable>(query); //DapperExtensionを使った処理 result.name += "qqqq111"; connection.Update<testTable>(result); connection.Close(); }testTableモデル
- モデルにはGetter Setterを必ず書くこと
public class testTable { public int test_id { get; set; } public string name { get; set; } }Swaggerを自動生成にさせる
Stoplight Studioを使います。
本当に使ってよかったOpenAPI (Swagger) ツール
開発にあたってのポイント
- Gtk2#はMono.Data.Sqliteを使う。Dapperと併用できた
- gtkのサンプルを探すのに苦労した。C# gtk hotexamples 調べたいメソッド名で調べるとgitに上がっているサンプルを一覧できるサイトが見つけることができた。
- モデルにはgetter setterを必ず書くこと
- 投稿日:2020-04-09T18:29:58+09:00
眺めて覚えるXamarin Hello World
iPhoneの電池が持たなくなった。携帯電話の寿命は、大体3年ぐらいだ。
はたして5万円以上の値打ちがあるのかが疑問である。
そこでAndroidにすることにした。
さくさく動くし、電池も3日もつ!
値段も5万円から2万円適正価格だ!
前から気になっていたXamarinを使ってC#でプログラムしてみた。
1.Visual studio 2019のインストールについては、色々な記事があるので参考にしてほしい。
私の買ったディバイスは、UMIDIGI Xだ。まず、メーカサイトからディバイスドライバーをダウンロードしてWindows 10にinstall しよう。
開発者モードにするには、「設定」アプリ内で「ビルド番号」を7回連続してタップ
Visual Studio 2019でプロジェクトを作成する。
Xamarin Formsを選択する。
Windows APPを作成するような感覚で開発できる。
空白のプロジェクトを作成する。
USBにより接続されたAndroidが表示されているか、確認する。
とりあえず下記のように表示されればOK
プログラムの内容を見てみよう
MainPage.xamlをダブルクリックするとソースが現れる。
XAMLはXMLをベースとしたマークアップ言語です。UIを定義するのに用いられます。MainPage.xaml<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="HelloWorld.MainPage"> <StackLayout> <!-- Place new controls here --> <Label Text="Welcome to Xamarin.Forms!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> </StackLayout> </ContentPage>MainPage.xaml.csusing System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using Xamarin.Forms; namespace HelloWorld { // Learn more about making custom code visible in the Xamarin.Forms previewer // by visiting https://aka.ms/xamarinforms-previewer [DesignTimeVisible(false)] public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); var layout = new StackLayout(); var lb = new Label() { Text = "Hello World",FontSize=40 }; layout.Children.Add(lb); this.Content = layout; } } }Xamlでうにゃうにゃ書いていたレアウトをプログラムで書くと上記のようになる。
多分、javaで書くよりすっきりしていて良い。
- 投稿日:2020-04-09T18:29:58+09:00
眺めて覚える C# Xamarin Hello World
iPhoneの電池が持たなくなった。携帯電話の寿命は、大体3年ぐらいだ。
はたして5万円以上の値打ちがあるのかが疑問である。
そこでAndroidにすることにした。
さくさく動くし、電池も3日もつ!
値段も5万円から2万円適正価格だ!
前から気になっていたXamarinを使ってC#でプログラムしてみた。
1.Visual studio 2019のインストールについては、色々な記事があるので参考にしてほしい。
私の買ったディバイスは、UMIDIGI Xだ。まず、メーカサイトからディバイスドライバーをダウンロードしてWindows 10にinstall しよう。
開発者モードにするには、「設定」アプリ内で「ビルド番号」を7回連続してタップ
Visual Studio 2019でプロジェクトを作成する。
Xamarin Formsを選択する。
Windows APPを作成するような感覚で開発できる。
空白のプロジェクトを作成する。
USBにより接続されたAndroidが表示されているか、確認する。
とりあえず下記のように表示されればOK
プログラムの内容を見てみよう
MainPage.xamlをダブルクリックするとソースが現れる。
XAMLはXMLをベースとしたマークアップ言語です。UIを定義するのに用いられます。MainPage.xaml<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="HelloWorld.MainPage"> <StackLayout> <!-- Place new controls here --> <Label Text="Welcome to Xamarin.Forms!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> </StackLayout> </ContentPage>MainPage.xaml.csusing System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using Xamarin.Forms; namespace HelloWorld { // Learn more about making custom code visible in the Xamarin.Forms previewer // by visiting https://aka.ms/xamarinforms-previewer [DesignTimeVisible(false)] public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); var layout = new StackLayout(); var lb = new Label() { Text = "Hello World",FontSize=40 }; layout.Children.Add(lb); this.Content = layout; } } }Xamlでうにゃうにゃ書いていたレアウトをプログラムで書くと上記のようになる。
多分、javaで書くよりすっきりしていて良い。
- 投稿日:2020-04-09T16:32:07+09:00
[完]Visual StudioとC#を初めて使ってブロック崩しゲームを作ってみた④
前回:Visual StudioとC#を初めて使ってブロック崩しゲームを作ってみた③
前回で一応完成していますが
今回はさらにゲームっぽくする為、機能追加します。
アウトライン
- 設定ボタン追加
- カウントダウン開始3秒
- 経過中タイム表示
- CLEAR表示(動きを付けたい)
- ランキング表示(アプリ起動中)
ディティール
- 設定ボタンの画面
- ボール加速 on/off(ラジオボタン)
- パドル移動距離 最大で1個分(スライドボタン)
CLEAR表示
気分でCLEAR表示作成から作っていきます!
JavaScriptで作れるようなポヨンポヨン動く文字を作りたかったのに
Windowsフォームじゃできない?みたいです。
なのでプロパティを活用して見た目をよくします。
CLEAR用のラベルだけ追加してサイズ、色、配置等はお任せです。
頑張っても古臭いデザインにしかなりませんでしたw初期値でCLEARを入れているので、
ブロック数が1以上のときに文字を変更します。
以下をform3_loadメソッドに追加。Form3.csif (Form1.blockNum > 0) { label7.Text = "NotGood.."; label7.ForeColor = Color.Black; }カウントダウン開始
これも数字が縮小していって次の数字を出したかったのですが難しいので
いや縮小させるだけならタイマーでサイズダウンさせましょう。Form1で以下ラベル作成
プロパティのFontでサイズを大きくします。これは48pt
追加コードは以下になります。
Form1.cspublic partial class Form1 : Form { Timer timerCount = new Timer(); //カウントダウンタイマー int countSize = 200; //カウント文字のサイズ int countNo = 3; //カウント数 public Form1() { label1.Font = new Font(label1.Font.OriginalFontName, countSize + 1); //カウントダウン初期表示サイズ指定 //カウントダウン開始 timer.Interval = 100; timerCount.Tick += new EventHandler(countDown); //timer.Trik:Timer有効時に呼ばれる timerCount.Start(); } private void countDown(object sender, EventArgs e) { if (countSize == 0) { countNo--; label1.Text = countNo.ToString(); countSize = 200; } if (countSize == 20 && countNo == 1) { timerCount.Stop(); //ゲームスタート countDownAfter(); } countSize -= 20; label1.Font = new Font(label1.Font.OriginalFontName, countSize +1); } private void countDownAfter() { //ゲームタイマー timer.Interval = 33; timer.Tick += new EventHandler(Update); //timer.Trik:Timer有効時に呼ばれる timer.Start(); //経過時間スタート keikaTime.Restart(); }①まずカウントダウン用のタイマーを作成
②タイマー有効時に呼ばれるcountDownメソッドを作成
③countDownAfterメソッド作成。カウントダウン後にゲームを開始するので
ゲーム中のタイマーと経過時間処理をそこへ移動。フォントの変更の仕方結構調べました。
この記事に感謝します。https://qiita.com/r-ngtm/items/276a6ee832bd32afed36文字ボックスのサイズを小さくしているので値が小さくなるにつれて
左上に寄ってしまいます。
画面のXY軸を半分にすると画面の中心になります。
そこからカウントダウンのラベルサイズの半径を引くと
画面の中心に表示されるように「なります。Form()とcountDown()でラベルをnewで作り出した後に位置を指定します。
「label1.Left」と「label1.Top 」の2行をそれぞれに追加します。Form1.cspublic Form1() { label1.Font = new Font(label1.Font.OriginalFontName, countSize + 1); //カウントダウン初期表示サイズ指定 label1.Left = (this.Width / 2) - (countSize / 2); label1.Top = (this.Height /2) - (countSize / 2); ・・・ private void countDown(object sender, EventArgs e) { label1.Font = new Font(label1.Font.OriginalFontName, countSize +1); label1.Left = (this.Width / 2) - (countSize / 2); label1.Top = (this.Height / 2) - (countSize / 2);「コントロール名.Left」でX軸、TopでY軸を位置指定できます。
ラベルの四角い背景が後ろと被らないように透明にします。
Form1()のlabel1.Top処理の下に書きます。Form1.cslabel1.BackColor = Color.Transparent; //背景透明化経過中タイム表示
新しくタイマーを作るのも面倒だじ、
定期処理のUpdate()に追加します。Form1.csForm(){ label2.BackColor = Color.Transparent; //背景透明化 ・・・ private void realTime() //リアルタイム表示 { label2.Text = keikaTime.Elapsed.ToString().Substring(6, 6); } ・・・ private void Update(object sender, EventArgs e) { //リアルタイム realTime();先ほどのlabel1の透明化処理の下にlabel2の透明化処理も書きます。
realTime()で表示するテキストを指定(リザルト画面の処理を丸パクリする)。設定ボタン追加
ここでイメージしている画面は、スマホ版バトロワのエイム感度の設定画面
上の画面はタブ切り替えでページが切り替わります。
ユーザコントロールを利用してこれを作成します。設定ボタンは後にして、先に設定画面を作ります。
Form4画面を追加します。
ツールボックス→すべてのWindowsフォーム→「TabControl」を画面に設置する。
テキストは対象タブを選択して、タブの画面エリア部をクリックし
そこからのプロパティでタブのテキストを変更できる(パドル距離・ボール加速)。
ツールボックス→すべてのWindowsフォーム→「TrackBar」を画面に設置する。
プロパティを変更します。Form4に記述するか、プロパティに直接打ちます。
trackBar1.Minimum = 1; //最小値
trackBar1.Maximum = 100; //最大値
trackBar1.Value = 50; //初期値
trackBar1.TickFrequency = 0; //メモリ刻む値
trackBar1.SmallChange = 1; //マウスで移動できる値
trackBar1.BackColor= Window; //とりあえず白く
trackBar1.TickStyle = Both; //つまみの形参考→TrackBarの基本
メモリを刻むのは今どきダサいのでしませんw
以下のようになったはずです。
左右にボタン、下にラベルを設置します。
TrackBarのイベントを作成します。
プロパティ→イベント→MouseMoveにbar_Move入力。Form4.csusing System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Breakout { public partial class Form4 : Form { public static int paddleMove { get; set; } //パドル距離 public Form4() { InitializeComponent(); label1.Text = trackBar1.Value.ToString(); //距離初期値 } //バー移動時 private void bar_Move(object sender, EventArgs e) { label1.Text = trackBar1.Value.ToString(); paddleMove = trackBar1.Value; } private void down_Click(object sender, EventArgs e) { trackBar1.Value --; bar_Move(sender, e); } private void up_Click(object sender, EventArgs e) { trackBar1.Value ++; bar_Move(sender, e); } } }Form2にて設定ボタン追加します。
プロパティのイベントのClickに「setting_Click」を入力しエンター押下。
以下の内容を追記Form2.csprivate void option_Click(object sender, EventArgs e) //設定押下時 { // Form4のインスタンスを生成 Form4 form4 = new Form4(); // form4を表示 form4.ShowDialog(); }Form1のパドル移動処理(KeyPressed)を変更します。
Form1.csprivate void KeyPressed(object sender, KeyPressEventArgs e) //押下毎 { if (Form4.paddleMove == 0) //設定行っていない場合 { Form4.paddleMove = 20; } if (e.KeyChar == 'a' && paddlePos.Left > 0) //A押下時 { this.paddlePos.X -= Form4.paddleMove; } else if (e.KeyChar == 's' && paddlePos.Right < this.Width) //S押下時 { this.paddlePos.X += Form4.paddleMove; } }今回はここまで
残りは後日追記します。未対応不具合メモ:
・スタート後画面閉じてもリザルト画面が表示される
・スタート前にパドル移動するとおかしな挙動感想
ここまでお付き合いいただきありがとうございました!
Visual StudioとC#を使ってみて。
Eclipseより楽しいし簡単に作れる!
入門はJavaよりC#選ぶべきだったかも・・
ただWindowsフォームだとCSSとかJavaScriptがないのは不便。
動きを付けるのには向いてなく、
本当に業務システム向けだなって感じでした。学びやすいからC#でスタートダッシュをして、
それから他の言語をやるのもありかと!
スコア毎にS~Dなどのランクをつけて表示するなど
色々いじって身につけるください!
1ファイルが長くなったり、ファイル数が増えてきたら
フォルダ―を追加したり共有ファイルを作ったりします。
実際の現場では何十何百とファイルがありますが
小分けにされているだけなので怖がらないように!興味もない業務システム作るのはあんまり楽しくないなあ。。
(次の案件がVisual Studio(C#)...)
- 投稿日:2020-04-09T13:48:18+09:00
お手軽Linux Guiアプリ開発 初級 前半
お手軽Linux Guiアプリ開発 初級 前半
開発内容
- GtkGUIでSqlite3を使う
- Dapperの導入 Dapperについてまとめてみた
- Dapper Extensionの導入 Dapperの拡張ライブラリ 比較検討
- Swaggerを使う Stoplight Studioなどを使う 使ってよかったOpenAPI (Swagger) ツール
- C#からPythonを実行する C#からPythonスクリプトを呼び出す
- DataGrideViewとModelのバインディングの実現 treeView
- RazurebyPiへのデプロイ
前半は5まで
開発環境
Mac
VisualStudioMac 2019
C#
Sqlite3VisualStudioMacにSqlite3の導入
NugetからSystem.Data.SQlite.Coreをインストールします
Sqliteを実行する
using System; using System.Data.SQLite; namespace sqliteTest { class Program { static void Main(string[] args) { SQLiteConnection connection = new SQLiteConnection(); SQLiteCommand command = new SQLiteCommand(); connection.ConnectionString = @"Data Source=パス"; connection.Open(); command.CommandText = "select * from testTable;"; command.Connection = connection; // SQLを実行します。 SQLiteDataReader reader = command.ExecuteReader(); while(reader.Read()) { var id = reader.GetValue(0); var name = reader.GetValue(1); Console.WriteLine("ID:" + id + " 名称:" + name ); } connection.Close(); } } }Dapperの導入
クエリーの結果をモデルにフェッチできたり、insert,Update時に値をmodelで渡して処理できます
NugetからDapperを導入します
Dapperの導入 Dapperについてまとめてみた
model.cspublic class testTable { public int test_id { get; set; } public string name { get; set; } }using System; using System.Data.SQLite; using Dapper; namespace sqliteTest { class Program { static void Main(string[] args) { SQLiteConnection connection = new SQLiteConnection(); connection.ConnectionString = @"Data Source=パス/test.sqlite"; connection.Open(); var qurey = "select * from testTable;"; var result = connection.Query<testTable>(qurey); foreach(var p in result) { Console.WriteLine("ID:" + p.test_id + " 名称:" + p.name); } connection.Close(); } } }Dapper Extensionの導入
ModelからInsert文、Update文、Delete文を自動生成でき、実行できます
NugetからDapperExtensions.NetCoreを導入します
必須 Sql文を[testTable].[test_id]から [test_id]に変更します
DapperExtensions.DapperExtensions.SqlDialect = new DapperExtensions.Sql.SqliteDialect();Dapper Extensionの導入 Dapperの拡張ライブラリ 比較検討
using System; using System.Data.SQLite; using Dapper; using DapperExtensions; namespace sqliteTest { class Program { static void Main(string[] args) { //Sql文を [testTable].[test_id]から [test_id]に変更する DapperExtensions.DapperExtensions.SqlDialect = new DapperExtensions.Sql.SqliteDialect(); SQLiteConnection connection = new SQLiteConnection(); connection.ConnectionString = @"Data Source=パス"; connection.Open(); //insert testTable testTable1 = new testTable(); testTable1.name = "aaaaaa"; connection.Insert<testTable>(testTable1); //Modelのフェッチ var qurey = "select * from testTable;"; var result = connection.QueryFirst<testTable>(qurey); //update result.name += "testtest"; connection.Update<testTable>(result); connection.Close(); } } }C#からPythonを実行する
Pythonのパスを取得する
$ which python
/usr/local/bin/python
test.pyimport sys if len(sys.argv) == 3: firstArgument = int(sys.argv[1]) secondArgument = int(sys.argv[2]) print(firstArgument + secondArgument) else: print('ArgumentException...')using System; using System.Collections.Generic; using System.Diagnostics; namespace sqliteTest { class Program { static void Main(string[] args) { var pythonInterpreterPath = @"パス/python"; var pythonScriptPath = @"パス/test.py"; var arguments = new List<string> { pythonScriptPath , "20", //第1引数 "30" //第2引数 }; var process = new Process() { StartInfo = new ProcessStartInfo(pythonInterpreterPath) { UseShellExecute = false, RedirectStandardOutput = true, Arguments = string.Join(" ", arguments), }, }; process.Start(); //python側でprintした内容を取得 var sr = process.StandardOutput; var result = sr.ReadLine(); process.WaitForExit(); process.Close(); Console.WriteLine("Result is ... " + result); } } }Swaggerの生成
Swaggerを作り。SwaggerCodegenでC#で書かれたAPIクライアントプログラムを生成します。
Stoplight Studioを使います
本当に使ってよかったOpenAPI (Swagger) ツール
DataGrideViewとModelのバインディンで表示
DataGrideViewとModelのバインディングの実現 treeView
簡単なデータベースアプリのプロト開発
https://www.monodevelop.com/documentation/
https://www.monodevelop.com/documentation/stetic-gui-designer/
https://ja.coder.work/so/gtktreeview
よい
https://www.mono-project.com/docs/gui/gtksharp/widgets/treeview-tutorial/GTK C# hotexamples 調べたいメソッド名で検索するとかなりよい
後半へ続く
- 投稿日:2020-04-09T07:52:42+09:00
[コピペでOK] C#でログを出力する
はじめに
C#でログを出力するLoggerを作成しました。
C#では、便利なライブラリがありますが、
ここでは、コピペですぐに使えるものを目指しています。機能としては下記の通りです。
- ログレベル
- ログローテート
- 出力先指定
下記にC#でログ出力を行うライブラリを紹介しているリンクを記載します。
実行環境
今回実行した環境は下記の通りです。
実行環境Microsoft .NET Framework 3.5C#の古いバージョンでも動作するように実装しています。
使い方
使い方は下記の通りです。
Logger log = Logger.GetInstance(); log.Error("error log."); log.Warn("warn log."); log.Info("info log."); log.Debug("debug log.");出力されるログは下記の通りです。
[2020-04-08 22:38:56.081][1][DEBUG] debug log. [2020-04-08 22:38:56.082][1][ERROR] error log. [2020-04-08 22:38:56.082][1][WARN] warn log. [2020-04-08 22:38:56.082][1][INFO] info log.「1」この数字は、プロセスIDを表示しています。
Loggerの実装
configでLoggerに関する設定を行います。
app.config<setting name="IS_LOGFILE" serializeAs="String"> <value>True</value> </setting> <setting name="LOG_LEVEL" serializeAs="String"> <value>3</value> </setting> <setting name="LOGDIR_PATH" serializeAs="String"> <value>./logs/</value> </setting> <setting name="LOGFILE_NAME" serializeAs="String"> <value>console</value> </setting> <setting name="LOGFILE_MAXSIZE" serializeAs="String"> <value>10485760</value> </setting> <setting name="LOGFILE_PERIOD" serializeAs="String"> <value>30</value> </setting>
- 「IS_LOGFILE」はログファイル出力フラグです。
- 「LOG_LEVEL」はログレベルです。
- 「LOGDIR_PATH」はログファイル出力ディレクトリです。
- 「LOGFILE_NAME」はログファイル名です。
- 「LOGFILE_MAXSIZE」はログファイル最大サイズ(Byte)です。
- 「LOGFILE_PERIOD」はログ保存期間(日)です。
Loggerクラスの実装は下記の通りです。
Logger.csclass Logger { /// <summary> /// ログレベル /// </summary> private enum LogLevel { ERROR, WARN, INFO, DEBUG } private static Logger singleton = null; private readonly string logFilePath = null; private readonly object lockObj = new object(); private StreamWriter stream = null; /// <summary> /// インスタンスを生成する /// </summary> public static Logger GetInstance() { if (singleton == null) { singleton = new Logger(); } return singleton; } /// <summary> /// コンストラクタ /// </summary> private Logger() { this.logFilePath = Settings.Default.LOGDIR_PATH + Settings.Default.LOGFILE_NAME + ".log"; // ログファイルを生成する CreateLogfile(new FileInfo(logFilePath)); } /// <summary> /// ERRORレベルのログを出力する /// </summary> /// <param name="msg">メッセージ</param> public void Error(string msg) { if ((int)LogLevel.ERROR <= Settings.Default.LOG_LEVEL) { Out(LogLevel.ERROR, msg); } } /// <summary> /// ERRORレベルのスタックトレースログを出力する /// </summary> /// <param name="ex">例外オブジェクト</param> public void Error(Exception ex) { if ((int)LogLevel.ERROR <= Settings.Default.LOG_LEVEL) { Out(LogLevel.ERROR, ex.Message + Environment.NewLine + ex.StackTrace); } } /// <summary> /// WARNレベルのログを出力する /// </summary> /// <param name="msg">メッセージ</param> public void Warn(string msg) { if ((int)LogLevel.WARN <= Settings.Default.LOG_LEVEL) { Out(LogLevel.WARN, msg); } } /// <summary> /// INFOレベルのログを出力する /// </summary> /// <param name="msg">メッセージ</param> public void Info(string msg) { if ((int)LogLevel.INFO <= Settings.Default.LOG_LEVEL) { Out(LogLevel.INFO, msg); } } /// <summary> /// DEBUGレベルのログを出力する /// </summary> /// <param name="msg">メッセージ</param> public void Debug(string msg) { if ((int)LogLevel.DEBUG <= Properties.Settings.Default.LOG_LEVEL) { Out(LogLevel.DEBUG, msg); } } /// <summary> /// ログを出力する /// </summary> /// <param name="level">ログレベル</param> /// <param name="msg">メッセージ</param> private void Out(LogLevel level, string msg) { if (Settings.Default.IS_LOGFILE) { int tid = System.Threading.Thread.CurrentThread.ManagedThreadId; string fullMsg = string.Format("[{0}][{1}][{2}] {3}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), tid, level.ToString(), msg); lock (this.lockObj) { this.stream.WriteLine(fullMsg); FileInfo logFile = new FileInfo(this.logFilePath); if (Settings.Default.LOGFILE_MAXSIZE < logFile.Length) { // ログファイルを圧縮する CompressLogFile(); // 古いログファイルを削除する DeleteOldLogFile(); } } } } /// <summary> /// ログファイルを生成する /// </summary> /// <param name="logFile">ファイル情報</param> private void CreateLogfile(FileInfo logFile) { if (!Directory.Exists(logFile.DirectoryName)) { Directory.CreateDirectory(logFile.DirectoryName); } this.stream = new StreamWriter(logFile.FullName, true, Encoding.UTF8) { AutoFlush = true }; } /// <summary> /// ログファイルを圧縮する /// </summary> private void CompressLogFile() { this.stream.Close(); string oldFilePath = Settings.Default.LOGDIR_PATH + Settings.Default.LOGFILE_NAME + "_" + DateTime.Now.ToString("yyyyMMddHHmmss"); File.Move(this.logFilePath, oldFilePath + ".log"); FileStream inStream = new FileStream(oldFilePath + ".log", FileMode.Open, FileAccess.Read); FileStream outStream = new FileStream(oldFilePath + ".gz", FileMode.Create, FileAccess.Write); GZipStream gzStream = new GZipStream(outStream, CompressionMode.Compress); int size = 0; byte[] buffer = new byte[Settings.Default.LOGFILE_MAXSIZE + 1000]; while (0 < (size = inStream.Read(buffer, 0, buffer.Length))) { gzStream.Write(buffer, 0, size); } inStream.Close(); gzStream.Close(); outStream.Close(); File.Delete(oldFilePath + ".log"); CreateLogfile(new FileInfo(this.logFilePath)); } /// <summary> /// 古いログファイルを削除する /// </summary> private void DeleteOldLogFile() { Regex regex = new Regex(Settings.Default.LOGFILE_NAME + @"_(\d{14}).*\.gz"); DateTime retentionDate = DateTime.Today.AddDays(-Settings.Default.LOGFILE_PERIOD); string[] filePathList = Directory.GetFiles(Settings.Default.LOGDIR_PATH, Settings.Default.LOGFILE_NAME + "_*.gz", SearchOption.TopDirectoryOnly); foreach (string filePath in filePathList) { Match match = regex.Match(filePath); if (match.Success) { DateTime logCreatedDate = DateTime.ParseExact(match.Groups[1].Value.ToString(), "yyyyMMddHHmmss", null); if (logCreatedDate < retentionDate) { File.Delete(filePath); } } } } }スレッドセーフにするために、lockを使用しています。
さいごに
ソースコードをGitHubに公開しています。
以上です。
- 投稿日:2020-04-09T07:00:51+09:00
[Unity]初心者 privateってなに?
環境
Unity 2019.3.7f1
privateってなに?
ざっくり簡単にいうと、変数やメソッドを他のスクリプトからアクセスさせないようにするもの
意図せず数値が書き換えられてしまうのを防止する最初は、
privateは他からアクセスできない
publicは他からアクセスできる
と覚えておく程度でOK!他のスクリプトで値を使う予定のない変数にはprivateをつけておけば無難。
privateは省略できる
初心者さんにはこれを一番伝えたい!
実は、変数宣言時にpublicやprivateなどの"アクセス修飾子"をつけないと
privateが省略されるかたちになっている他の記事を見る際は、
・privateを省略するパターン
・privateをあえて書くパターン
がありますので、この点を頭において見ていくと良いです。私は最初これがわからずもやもやした気持ちで参考記事を見ていました。
楽しいUnityライフを!
- 投稿日:2020-04-09T07:00:51+09:00
[Unity]初心者 privateってなに?
環境
Unity 2019.3.7f1
privateってなに?
ざっくり簡単にいうと、変数やメソッドを他のスクリプトからアクセスさせないようにするもの
意図せず数値が書き換えられてしまうのを防止する最初は、
privateは他からアクセスできない
publicは他からアクセスできる
と覚えておく程度でOK!他のスクリプトで値を使う予定のない変数にはprivateをつけておけば無難。
privateは省略できる
初心者さんにはこれを一番伝えたい!
実は、変数宣言時にpublicやprivateなどの"アクセス修飾子"をつけないと
privateが省略されるかたちになっている他の記事を見る際は、
・privateを省略するパターン
・privateをあえて書くパターン
がありますので、この点を頭において見ていくと良いです。私は最初これがわからずもやもやした気持ちで参考記事を見ていました。
楽しいUnityライフを!
- 投稿日:2020-04-09T02:38:50+09:00
Microsoft.Extensions.Configuration を使って、INI ファイルに書いた設定を読み込む
Microsoft.Extensions.Configuration を使って、INI ファイルに書いた設定を読み込む
exe.config はずっと微妙だなあと思っていたのですが、Microsoft 謹製の INI ファイルから設定を読む手段が提供されたので、それを使ってみる. 例として以下の INI ファイルを読むコードを作成する. 書いたコードは GitHub にも上げてある.
config.ini[ConnectionStrings] Database=xxx [AppSettings] UserName=foo Password=bar RetryCount=3Console App (.NET Core) プロジェクトを作成する. TargetFramework が netcoreapp3.1 (.NET Core 3.1) で作成される. 要求は .NET Standard 2.0 なので .NET Framework 4.6.1 や、.NET Core 2.0 でも動くはず.
次に
Microsoft.Extensions.Configuration.Ini
とInstall-Package Microsoft.Extensions.Configuration.Binder
を nuget インストールする. これを書いている時点では 3.1.3 がインストールされる.Install-Package Microsoft.Extensions.Configuration.Ini Install-Package Microsoft.Extensions.Configuration.Binderそして、セクション毎に情報を詰めるクラスを書いていく.
ConnectionStringsConfig.csnamespace ConsoleApp1 { public class ConnectionStringsConfig { public string Database { get; set; } } }AppSettingsConfig.csnamespace ConsoleApp1 { public class AppSettingsConfig { public string UserName { get; set; } public string Password { get; set; } public int RetryCount { get; set; } } }最後にそれらセクション毎のクラスをまとめ上げるクラスと、INI ファイルから設定を読み込むメソッドを書いて完成.
AppConfig.csusing Microsoft.Extensions.Configuration; namespace ConsoleApp1 { public class AppConfig { static AppConfig Instance; public ConnectionStringsConfig ConnectionStrings { get; set; } public AppSettingsConfig AppSettings { get; set; } public AppConfig() { } public static AppConfig Get() { if (Instance != null) return Instance; Instance = new ConfigurationBuilder() .AddIniFile(".\\config.ini") .Build() .Get<AppConfig>(); return Instance; } } }以下のように簡単に設定内容にアクセスできる.
Program.csusing System; namespace ConsoleApp1 { class Program { static readonly AppConfig Config = AppConfig.Get(); static void Main(string[] args) { Console.WriteLine(Config.ConnectionStrings.Database); Console.WriteLine(Config.AppSettings.UserName); Console.WriteLine(Config.AppSettings.RetryCount); Console.Read(); } } }
- 投稿日:2020-04-09T00:37:18+09:00
C# で WebAPI を呼び出して JSON の特定の値を出力させる
備忘録として、C# コンソールアプリで、WebAPI を呼び出し、レスポンスで得られた JSON の特定の値を取り出して出力する方法を記載します。
使用する WebAPI
今回は例として、天気予報を教えてくれる API
OpenWeatherAPI
を使用します。これは以下サイトで Sign Up すると無料で使用でき東京の天気予報も出力できるのでいろいろ試したいときに便利です。
参考情報 : OpenWeather
この API でフリーで使用できるものの中に今の天気を出力できる API があります。以下の様なリクエストで天気情報を得ることが来ます。http://api.openweathermap.org/data/2.5/forecast?q=Tokyo,jp&units=metric&APPID={Your API Key}この API で得られる JSON は以下のような形になります。
{ "coord": { "lon": 139.69, "lat": 35.69 }, "weather": [ { "id": 800, "main": "Clear", "description": "clear sky", "icon": "01n" } ], "base": "stations", "main": { "temp": 15.49, "feels_like": 10.92, "temp_min": 12.22, "temp_max": 17.78, "pressure": 1011, "humidity": 59 }, "visibility": 10000, "wind": { "speed": 5.7, "deg": 240 }, "clouds": { "all": 0 }, "dt": 1586359041, "sys": { "type": 1, "id": 8074, "country": "JP", "sunrise": 1586376987, "sunset": 1586423326 }, "timezone": 32400, "id": 1850144, "name": "Tokyo", "cod": 200 }ではこの出力結果を C# で処理してみます。
C# で JSON を取り扱う
特定の値を抜き出して文字列を作成し、Console に出力するサンプルコードは以下になります。
using System; using System.Linq; using System.Threading.Tasks; using System.IO; using System.Net.Http; using Newtonsoft.Json.Linq; using Newtonsoft.Json; using System.Net; namespace ConsoleApp { class Program { static void Main(string[] args) { String url = "http://api.openweathermap.org/data/2.5/weather?q=Tokyo,jp&units=metric&APPID={Your API Key}"; WebRequest request = WebRequest.Create(url); Stream response_stream = request.GetResponse().GetResponseStream(); StreamReader reader = new StreamReader(response_stream); var obj_from_json = JObject.Parse(reader.ReadToEnd()); var forecast_sum = obj_from_json["weather"][0]["main"]; var forecast_des = obj_from_json["weather"][0]["description"]; var forecast_max_temp = obj_from_json["main"]["temp_max"]; var forecast_min_temp = obj_from_json["main"]["temp_min"]; var forecast_hum = obj_from_json["main"]["humidity"]; var forecast_wind = obj_from_json["wind"]["speed"]; string forecast_output = "Tokyo is " + forecast_sum + " now. Description is " + forecast_des + ". Max tempreture is " + forecast_max_temp + "℃. Min tempreture is " + forecast_min_temp + "℃. Humidity is " + forecast_hum + "%. Wind is " + forecast_wind + "m/s. Have a good day!"; Console.WriteLine(forecast_output); } } }出力結果は以下になります。
非常に単純なプログラムですが、JSON を扱いなれていないと以外と引っ掛かります。個人的な考えですが、WebAPI で 取得した JSON の特定の値を取り出す際は、まずは JSON 整形サイトで値のキーを確認するのが便利です。
例えば JSON 整形サイトは以下の様なものがあります。
参考情報 : JSON Pretty Linter Ver3
このサイトでは API で得られた JSON を読み込ませると、得られた値のキーを教えてくれます。例えば今回の API で得られた JSON を以下の様に貼り付けてみます。
すると、画面したの Viewer にキー付きの整形された JSON が出てきます。これは非常に便利です。
こういった JSON 整形 Website を使用すると、より分かりやすく JSON を扱うことができるのではないでしょうか。
以上、簡単な備忘録でした。
- 投稿日:2020-04-09T00:11:27+09:00
SwiftとC#の書き方比較
はじめに
C#を書くにあたり、「Swiftでいうと・・・これ?
」「なんだ、これは?
」と
かなり困惑したので、比較表を作ろうと思いました。
私自身、初心者なので同じ初心者の方々のお役に立てれば嬉しいです
記事の内容に関して、勘違いもあると思いますし、これが全てではありません。
色々な記事を読んで、自らの手をどんどん動かしてみてください!変数と定数
Swift//変数 var hoge: String = "Hello" //定数 let fuga: Int = 810C#//変数 string hoge = "Hello"; //定数 const int fuga = 810;
- ポイント
- Sfiftでは型名は後 / C#では型名は前
- C#では文末にセミコロンが必要(初めは忘れがちです
)
- 右辺の型が自明である場合はわざわざ型を記載しなくても良いですが、本文では記載しておきます。
型変換(StringとIntで)
Swift//String → Int var hoge: String = "114" var fuga: Int = Int(hoge)! //Int → String var hoge: Int = 514 var fuga: String = String(hoge)C#//String → Int string hoge = "114"; int? fuga = int.Parse(hoge); //Int → String int hoge = 514; string fuga = hoge.ToString();
- ポイント
- Swiftは 型(値)
- C#はメソッドを使う(変換する型の組み合わせによっては他のやり方もある)
配列
Swift//配列の作成 var someInts: [Int] = [] //要素の追加 someInts.append(1) someInts += [2,3,4,5] print(someInts) //[1,2,3,4,5]C#//要素数が可変なリストの作成 List<int> someInts = new List<int>(); //要素の追加 someInts.add(1); //これがC#の配列宣言 int[] addInts = new int[] {2,3,4,5}; someInts.AddRange(addInts); Console.WriteLine(someInts); //[1,2,3,4,5]
- ポイント
- Swiftの配列は要素数が可変
- C#の配列は要素数が固定(Listは可変)
for文
Swift//昇順処理なのでC#みたいに色々と書かなくてもよい for i in 1...5 { print(i) //1,2,3,4,5 }C#//カッコ内で色々と書く //iの開始値は1,iは5まで繰り返す,iはfor文の処理を終えるごとに+1する for(int i = 1; i <= 5; i++) { Console.WriteLine(i); //1,2,3,4,5 }
- ポイント
- Swiftのfor-in文は昇順処理をしてくれるため、簡潔に記載できる(Swift3.x~)
- C#はforのカッコ内で色々と書く必要がある
- map,foreachなど色々ありますが、今回は最も基本的なもので比較しています。
if文
Swiftvar num: Int = 5 //カッコなしで書ける if num == 5 { print("5だよ") } else { print("5じゃないよ") } // 5だよC#int num = 5; //カッコがいる if(num == 3) { Console.WriteLine("3だよ"); } else { Console.WriteLine("3じゃないよ"); } //3じゃないよ
- ポイント
- 書き方はそんなに違いなし!?
関数
Swift//func 関数名(ラベル 引数名: 型) -> 戻り値の型 func plusWithNum(_ num1: Int, _ num2: Int) -> Int{ return num1 + num2 } //ラベルにアンスコを書くことでラベルなしで呼べる plusWithNum(1,5) //6 //ちょっと余談 //func 関数名(ラベル省略 引数名: 型) -> 戻り値の型 func plusWithNum(num1: Int, num2: Int) -> Int{ return num1 + num2 } //引数名がラベルになるが、呼び出すときに記述する必要あり plusWithNum(num1: 1, num2: 5) //6C#//戻り値の型 関数名(型 引数名) int plusWithNum(int num1, int num2) { return num1 + num2; } //普通に引数の型と同じものを入れたらよい plusWithNum(1,5) //6 //追記 // 名前付き引数での呼び出し PlusWithNum(num1: 1, num2: 5); // 名前付き引数の場合, 順番を前後させても問題ない PlusWithNum(num2: 5, num1: 1);
- ポイント
- Swiftは「->」の後が戻り値の型で関数を使用するときに引数にはラベルが必要
- C#は関数名の前が戻り値の型で素直に引数を入れたらよい
C#もSwiftのように引数名を書いて呼び出せるようです(@Midoliy さん、ありがとうございます!)
さいごに
ざっくりと基本文法の比較を書いてみました。
これはほんの一部に過ぎません(氷山の一角ですらない)
どんどん検索をして知識を深めていきましょう(私も頑張ります)
この記事が最初の1歩を踏み出す助けになれたら幸いです。
今後はSwiftのことを中心に記事を書いていこうと思うので、よろしくお願いします参考サイト