20211014のC#に関する記事は6件です。

Gitには無いpre-checkoutフックの実験的実装

Gitへの要求はどこまでも続きそうです。 すみません、Gitのmasterリポジトリをいじる記事ではありません。  Gitの外側から制御して、新規のフック処理を実装するものです。  Gitフックはリモートリポジトリ方向へは手厚いですが、ローカルワークツリー方向へはニーズが無いのか、さっぱりです。  今回は、クライアントサイドフックのcheckout処理前を実装しようと思います。贅沢を言えばきりがないので、checkoutコマンドの一部だけ対応します。 git checkout -- <ファイル> で、過去のコミット分にファイル単位で戻す。 環境 Windows10 64bit home 21H1 VisualStudio 2019 Community 16.11.4 C# .NET 4.8 Git for Windows 2.33.0.2-64-bit TortoiseGit 2.12.0.0-64bit どんな感じでフックを作るのか。 ①binフォルダをbin2フォルダにコピー ②binフォルダに今回作るGit.exeを配置(上書きで) ③リポジトリの.git/hooksフォルダにフックスクリプトを配置 Git.exeを使う人は、bin2フォルダは知らないから、binフォルダのGit.exeを呼び出すことになる。そこでコマンド解析し、pre-checkoutフックを呼び出すこととする。 実際の仕事は、bin2フォルダのオリジナルのGit.exeにお願いする。 おまけで、ログファイルも作ってみる。 ラッパー的な実装ということになります。 今回作るもの .NETのコンソールアプリケーションを作ります。  実は、TortoiseGitを推してまして、TortoiseGitの『このリビジョンに戻す(E)』を選択されたときのフックが欲しくて、こんなことになっています。  Git.exeの処理結果は標準出力で受け取ることができます。なので、子プロセスとしてオリジナルのGit.exeを呼び出し、その標準出力をそのまま今回作るGit.exeの標準出力とする。そうすると、Git.exeを呼び出した人は、変なツールを実行しているとも気が付かずに、Gitを正しく操作できてしまいます。 Git.exe(ログファイル出力対応版)を作る できました。 コンソールアプリケーション(.NET Framework)で.NET4.8のプロジェクトを作りました。プロジェクト名は『git』で。 Program.cs using System; using System.IO; using System.Text; namespace git { class Program { //リポジトリフォルダ const string REPOSROOT = @"C:\WORK\test\"; //Gitコマンドログファイル const string LOGFILEPATH = REPOSROOT + @".git\hooks\git.log"; //オリジナルGitコマンドEXE const string GITCMD = @"C:\Program Files\Git\bin2\git.exe"; static void Main(string[] args) { string parm = ""; System.Diagnostics.Process p = null; string results = ""; //コマンドラインパラメータ連結 parm = string.Join(" ", args); //ログファイル出力 File.AppendAllText(LOGFILEPATH, $"{DateTime.Now} : git {parm}\n"); //オリジナルGitコマンド実行 p = new System.Diagnostics.Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardInput = false; p.StartInfo.CreateNoWindow = true; p.StartInfo.WorkingDirectory = REPOSROOT; p.StartInfo.FileName = GITCMD; p.StartInfo.Arguments = parm; //UTF8を使っている。 p.StartInfo.StandardOutputEncoding = Encoding.UTF8; p.Start(); results = p.StandardOutput.ReadToEnd(); p.WaitForExit(); p.Close(); //オリジナルGitコマンドの標準出力を、そのまま自分の標準出力とする。 //バイナリを使わないと一部文字化けが発生する。 //『あいうえお.bat』等 byte[] wkBuff = System.Text.Encoding.UTF8.GetBytes(results); Stream stdout = Console.OpenStandardOutput(); stdout.Write(wkBuff, 0, wkBuff.Length); stdout.Close(); } } }  リポジトリのパス等を固定で持っていますが、configファイルにでも設定するように修正すれば汎用性は上がります。  まずは、このコマンドログファイル出力のみのバージョンで、お目当てのコマンドが取れているか確認が大事です。 動かしてみる TortoiseGitで、過去のコミット分のファイルの右クリックで、『このリビジョンに戻す』を選択します。 きちんと、『aaa.bat』のcheckoutが取れていますね。 Git.exe(pre-checkoutフック対応版)を作る Program.cs using System; using System.IO; using System.Text; namespace git { class Program { //リポジトリフォルダ const string REPOSROOT = @"C:\WORK\test\"; //Gitコマンドログファイル const string LOGFILEPATH = REPOSROOT + @".git\hooks\git.log"; //オリジナルGitコマンドEXE const string GITCMD = @"C:\Program Files\Git\bin2\git.exe"; //Bashコマンド const string BASHCMD = @"C:\Program Files\Git\bin\bash.exe"; //フックスクリプト const string HOOKSH = @".git\hooks\pre-checkout"; static void Main(string[] args) { string parm = ""; System.Diagnostics.Process p = null; string results = ""; //コマンドラインパラメータ連結 parm = string.Join(" ", args); //ログファイル出力 File.AppendAllText(LOGFILEPATH, $"{DateTime.Now} : git {parm}\n"); //pre-checkoutフック if(args[0] == "checkout" && args[2] == "--") { //ログファイル出力 File.AppendAllText(LOGFILEPATH, $"{DateTime.Now} : pre-checkout\n"); //スクリプト実行コマンド実行 p = new System.Diagnostics.Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardInput = true; p.StartInfo.CreateNoWindow = true; p.StartInfo.WorkingDirectory = REPOSROOT; p.StartInfo.FileName = BASHCMD; p.StartInfo.Arguments = HOOKSH + " " + parm; p.Start(); p.WaitForExit(); p.Close(); } //オリジナルGitコマンド実行 p = new System.Diagnostics.Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardInput = false; p.StartInfo.CreateNoWindow = true; p.StartInfo.WorkingDirectory = REPOSROOT; p.StartInfo.FileName = GITCMD; p.StartInfo.Arguments = parm; //UTF8を使っている。 p.StartInfo.StandardOutputEncoding = Encoding.UTF8; p.Start(); results = p.StandardOutput.ReadToEnd(); p.WaitForExit(); p.Close(); //オリジナルGitコマンドの標準出力を、そのまま自分の標準出力とする。 //バイナリを使わないと一部文字化けが発生する。 //『あいうえお.bat』等 byte[] wkBuff = System.Text.Encoding.UTF8.GetBytes(results); Stream stdout = Console.OpenStandardOutput(); stdout.Write(wkBuff, 0, wkBuff.Length); stdout.Close(); } } } ログファイル出力の下に少しだけ追加しました。 Bashシェルスクリプトを実行しますが、Bash.exeにお願いしているだけです。 pre-checkoutフックスクリプトを作る hooksフォルダに配置しました。 pre-checkout #!/bin/sh cd `dirname $0` pwd echo `date` "pre-checkout start" >> pre-checkout.txt echo `date` '$1 =' "$1" >> pre-checkout.txt echo `date` '$2 =' "$2" >> pre-checkout.txt echo `date` '$3 =' "$3" >> pre-checkout.txt echo `date` '$4 =' "$4" >> pre-checkout.txt echo `date` "pre-checkout end" >> pre-checkout.txt echoだけのダミーです。 動かしてみる もう一度、同じことをします。 ログファイルに『pre-checkout』が出力されています。  フックスクリプトのデバッグ用テキストにコマンドラインパラメータが渡っていったのが出力されています。  ここで入手した、ハッシュとファイル名を元ネタとして、何かできそうな気がしました? 作ってみて  VisualStudioのようにGit直結でというようなツールばかりではないので、手動での操作が介在するため、ミスはさけられないのです。そこで、素直にGitフックでチェックしたり、なんとかしたりすればOKでは?発想となるのです。  セットものとして管理したくなったものは、いっしょにコミットしたり、チェックアウトしたくなるのです。『元に戻すのなら、2ファイル同時にチェックアウトして、同期をとって!!』的なルールを決めていても、きびしい感じです。  少しいいかげんな作りですが、メンテできる人がいれば、まあまあ使えそうな感じもします。記事に汎用性を持たせるために、pre-checkoutスクリプトはBashシェルスクリプトにしてますが、Git for Windowsなので、PowerShell直接呼出しのほうが、メンテしやすいかもしれません。  本当は、TortoiseGitの機能のフックスクリプトにpre_checkout_hookがあればうれしいです。TortoiseGitのpre_commit_hookフックスクリプトは画面でチェックを付けた管理外のファイル名も参照できるので、楽々です。  フック機能はうまく使えば楽になりますが、やりすぎは厳禁かもしれません。今回のはセーフかな?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

.NETネットワーク2 メモ

参考資料 .NETネットワーク・プログラミング入門 @IT ネット基礎3 この記事は「.NETネットワーク1 メモ」の続きです まだ読んでない人は上記↑の記事を読んでから戻ってきてください? ソケット・インターフェイス TCP/IPを用いてデータの送受信を行うと、異なるプラットフォーム(WindowsやMacなどのOSのこと)間でも通信することが可能である。 しかし開発する際には通信手順を細かく実装しなくてはならない。 これをより簡単に実装するようにと開発されたのがソケットインターフェース。 ソケットインターフェースを利用することでTCP/IPの具体的な通信手段や仕組みを知らなくても開発者はソケットの仕組みに沿ってプログラムを記述すれば通信を実装することが可能となる。 尚、ソケットインターフェースはAPI(第三者が開発した機能)であるため、TCP/IPを意識して開発を進めるよりは何倍も楽に開発できるような機能が多く実装されているため開発者は通信をよりスピーディーに実装することが可能となります。 .NET(C#の開発環境)ではソケット通信を行うためのクラスが用意されています。 Socketクラス(System.Net.Sockets名前空間) .NETネットワーク・プログラミングにおける選択肢 以下はソケット通信、.NETリモート処理、Webサービスからなるネットワーク通信方法である。 今回使用するのは.NETリモート処理です。 上記の表に書いてある通り、Javaやその他プラットフォームとの通信はできません。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ifLinkにサイコロIMSが新たに追加になりました。

はじめに ifLinkマイクロサービスを開発している八教と申します。 新たに3つのサイコロ出目及び出目の合計を取得し、ifLinkに通知するIMSが追加されましたので、 紹介させていただきます。 ifLinkとは サイコロIMSとは 3つのサイコロの出目、または出目の合計をifLinkのIFとして設定できます。 例えばIF条件をサイコロ出目の10以上とし、サイコロを振って10以上が出た場合に「あたり!」をトーストメッセージIMSで表示できます。 サイコロで遊ぶまで サイコロで遊ぶまでに以下の準備が必要です。 1.IAIIMSをインストールする   IAIIMSはサイコロIMSとifLinkをつなげる為に必要です。   以下リンクよりインストールしてください。   https://dev.iflink.link/ 2.SaicoroIMSをインストールする   さいころゲーム本体で、以下リンクのReleasesのSaicoroGame.apkをダウンロードしてください。   https://github.com/ifLinkOpenCommunity/SaicoroIMS 3.ルールを作成・配信する   IF条件で「Saicoro-Game-ToifLink」を選択してください。  条件は以下の通りです  ①.サイコロの目が設定通りなら    3つのサイコロの出目が設定した値と一致したらTHENが起動します    出目の順番はサイコロを振った順(ランダムで振られます)  ②.サイコロの目の合計値が設定通りなら    3つのサイコロの出目の合計値が設定した値と一致したらTHENが起動します  ➂.サイコロの目の合計値が設定以上なら    3つのサイコロの出目の合計値が設定した値以上ならTHENが起動します  ④.サイコロの目の合計値が設定以下なら    3つのサイコロの出目の合計値が設定した値以下ならTHENが起動します 4.SaicoroGameで遊びましょう!   以下アイコンをタップしてサイコロゲームを起動します。 起動すると何も表示されていない画面が表示されます。 画面をタップするとサイコロが振られます。 サイコロの動きが止まると出目が確定します。 確定した出目と出目の合計がトーストで表示されます。 IFで設定した条件に合致するとTHENが起動しトーストメッセージ「あたり!」が表示されます。 是非お試しいただければと思います。 【検証端末】  Pixel 4a XL Androidバージョン11  Oppo A5 2020 Androidバージョン10
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity] 重なり合うボタンを処理する

全てのボタンが同じtransformの子になっている前提で、 重なり合っているボタンをこんな風に処理したい 一番簡単なのは、OnClick()で button.gameObject.transform.SetAsFirstSibling(); のように最背面に移動してしまうことなのですが、これだと次のボタンが押せるようになる代わりに表示も背面に隠れてしまいます。 そこで、 for (int i = 0; i < transform.childCount; ++i) { UnityEngine.UI.Image img = _transform.gameObject.GetComponent<UnityEngine.UI.Image>(); if (transform.GetChild(i).Equals(_transform)) { img.color = Color.red; img.raycastTarget = false; transform.GetChild(i).SetAsLastSibling(); // 今回選択したものを最前面に } else if (!img.raycastTarget) // 前回最前面だったものを最背面にする { img.color = Color.white; img.raycastTarget = true; transform.GetChild(i).transform.SetAsFirstSibling(); } } のように、今回選択したものは raycastTarget をfalseにして押せなくしつつ最前面に、前回選択していたものはraycastTarget を元に戻しつつ最背面に送ることで、選択したものを最前面に残しつつ、後ろのボタンを押せるようになります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#のWindowsフォームアプリケーション(.NET Framework)でコンボボックスの設定

概要 デフォルトの状態でコンボボックスを設置するとユーザーが編集可能なコンボボックスになってしまうので、ユーザーが選択だけできるコンボボックスを作ります。 作り方 フォームにコンボボックスを配置 コンボボックスのNameはEnableComboBox 今回のコンボボックスの目的はユーザーに「有効」「無効」を選択させること。 コード コンストラクタに初期設定を記載。 SelectedIndexで初期値を設定。 EnableComboBox.DropDownStyle = ComboBoxStyle.DropDownList;は、編集不可の設定。 UserSetForm.cs using 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 WindowsFormsApp1 { public partial class UserSetForm : Form { public UserSetForm() { InitializeComponent(); EnableComboBox.Items.Add("有効"); EnableComboBox.Items.Add("無効"); EnableComboBox.SelectedIndex = 0; EnableComboBox.DropDownStyle = ComboBoxStyle.DropDownList; } } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity設計入門:第1章「ModelとView」・理論編

Unity設計入門の目次はこちら はじめに Model View Controller Presenter ViewModel etc... 設計について調べると必ずと言っていいほどこれらの用語が出てきます。 今回はこの中で「Model」と「View」について根本的に理解することを目指しましょう。 Modelとは フロントエンド・バックエンド・ゲームなど文脈によって定義や使われ方が異なる場合が多いです。 結果的に「データベースいじるやつ」とか「ビジネスロジック(Unityだとゲームロジック)」とか言われて、あいまいな理解になってしまうこともあるでしょう。 今回は「画面がなくてもゲームの本質として存在するような処理とデータのこと」として定義します。 具体的に考えてみましょう。 例えば、テトリスでは、「横一列にブロックが並んだら消す」とか「ランダムにテトリミノ(4つブロックがつながったアレ)を選ぶ」という処理は3DSで実装しようが、スマホゲームで実装しようが、Unityを使おうが、UE4を使おう、なんならコンソールアプリケーションとして実装しようが変わりません。このような処理をModelと呼びます。 また、「現在の盤面の状態」も同様に、どのプラットフォームで実装しようと変わらない画面に依存しないデータです。このようなデータもModelと呼びます。 具体的なアプリケーション実装においても、判断に迷った場合には「これ、ゲームエンジン移植しても変わらないコードになるかな?」と自問自答すれば良いと思います。 Viewとは Viewに関しては、「見えるもの!」という分かりやすい基準があるのでそこまで認識にずれが生じるものではないかと思います。むしろ、Viewじゃないものを無理やりViewに抱え込んでViewが爆発することの方が多い気がします。 そこで、今回はあえて「見えるもの」ではなく、「Unityがないと絶対に動かせないもの」と定義したいと思います。 例えば、transformを操作したり、Monobehaviourを継承したりしている部分です。 これはなぜかというと、Unityがあまりに強力だからです。Webだと、根本的なデータは全部サーバーに存在するのでModelときっちり別れさせざるを得ないですし、同じC#でもWPFなどだと厳格にViewが区切られていて、他の部分からViewにアクセスする手段がバインディングを除くとあまりないです。(このあたりの話はUnityと協調するためのアーキテクチャ『MVP4U』という記事でも触れられているます。) それに対して、Unityはその気になればすべてのロジックをMonobehaviourで完結させることが出来ます。Viewをいくらでも拡大解釈できるのです。したがって、Unityの文脈においては「Unityがないと絶対に動かせないもの」という定義がより適切だと考えられます。 ModelとViewを分離するとよい理由 1. 再利用性が上がる Modelは、その定義から「どんな画面でも使えるデータと処理」の集合体です。これはつまり、全画面・シーンで使うことが出来るようなデータと処理がまとまった、と言うことです。もしも、ModelとViewが結合していた場合、Modelが使いたくても、Viewが抱き合わせでついてきてしまうので、Viewの持つ「特定の画面特有の他では絶対使えない処理」のせいで再利用が厳しくなってしまいます。 2. Modelのテストが容易になる Viewから分離されたModelは純粋なC#のプログラムです。すなわち、簡単にユニットテストを書ける存在だということです。これは、コードを安定化させてくれます。テストのメリットについてはここ以外でも大量に語られているのであえて書くことはしません。 「テストなんて書かないよ!俺は趣味でUnityやってんだよ面倒なことやってられっか!」みたいな人にとっても価値のある存在です。というのも、テストが容易な設計それ自体が、周囲との依存関係を少なくして、コードの影響範囲を明確にした設計ということなので、最低限の品質を担保してくれるからです。 また、「テストを書いて仕様変更したら悲しくなるからやだ」みたいな人にとっても有用です。Viewの変化に比して、Modelの変更は圧倒的に起こりにくいです。Modelのコア部分にテストを書いておくことは効率のいい投資になります。 3. Unityの再生ボタンを押す回数が減る Viewは実行コストが桁外れに大きいです。なぜなら、その定義から「Unityの再生ボタンを押して、実行を待って、ボタンを押して反応を見て、インスペクタから値をチェックして、ヒエラルキービューをチェックして…」といった手作業でのチェック回数が増えるからです。2.で触れたModelのテストの容易さとは異なり、相当苦労しないと自動化などが出来ません。ModelとViewを分離することでViewが小さくなり、煩わしい作業が減ります。 「Unityでいい設計をしたい場合には、Unityから離れてコードを書かないといけない」ということを覚えておきましょう。 ( PureなC#を書くことの重要性についてはUnityにおける「設計レベル」を定義してみた という記事が参考になります) 4. 見た目を変更するコストが下がる 「ボタンの色を変更したらバグが発生した」とか「レイアウトを変えたら動かなくなった」とかの不具合による負担が減ります。 その理由は、「見た目のバグは絶対にViewに存在する」という確証が持てるからです。いままで動いていたということは、Modelにおかしな点はないということですから、見るべきコードの範囲が減ります。 また、「Viewが表示に徹すれば必然的にViewがシンプルになるのでバグを埋め込みにくく、不具合自体が減る」「Viewに依存したロジックを書くこと自体が出来なくなり、見た目の変更がバグを誘発する状況を作りにくくできる」といった理由から、見た目の変更、すなわちViewの柔軟性が上がります。 Viewの柔軟性が下がる原因のうち、「見た目変えたらボタンの位置や色に依存するロジックが壊れるからやりたくない」というものを完全に排除できます。 詳しくは、補足記事を参照してください。 5. 純粋なオブジェクト指向による開発が出来る ショッキングな書き方をすれば、実はUnityは、純粋なオブジェクト指向プログラミングを破壊する存在と言っていいです。 Unityの根本的な設計思想は機能ごとにコンポーネントを作ってそれを組み合わせたゲームオブジェクトによってゲームを構成することにあります。Unityはコンポーネント指向のゲームエンジンなのです。 したがって、ユーザーが定義できるプログラムはUnity上に存在する限りはMonobehaviourに限られてしまいます。 C#では多重継承が許されていないので、ユーザーはMonobehaviourを継承する限りは、他のクラスを継承することはできず、オブジェクト指向の機能は制限されてしまいます。 これは、ソフトウェア開発の方針の違いであって、優劣がつくものではありません。しかし、すくなくともModelを開発する段階においては、コンポーネント指向が足かせに働くことも多くなってしまいます。詳しくは、補足記事(10/20投稿)を参照してください。 ModelとViewが分離した状況下では、ModelはUnityの存在を知らない(今回の定義によれば、using UnityEngineした瞬間にそれはViewとなる)ので、Modelは純粋なオブジェクト指向の技法を用いてプログラムを書くことが出来ます。 ソフトウェア工学の書籍で学んだ技法を生かそうとしても、「実際問題Unityだとそう書いたら動かんじゃんどうすんの!」みたいに嘆く必要はもうないのです。 ModelとViewの分離の達成度のチェック項目 Modelが純粋なC#のみで構成されている ModelはUnityのことを全く意識していないつくりである。using UnityEngineしていない。また、「特定のボタンの表示可否」とか画面ありきの情報をもっていない Viewが十分に小さい。理想は、流し込まれたデータを一直線に処理して条件判断をしないViewであること おわりに ModelとViewを分離したほうがいいというのは、多くの記事で暗黙の了解として扱われがちな事項ですが、初めてMVXアーキテクチャに触れる際にはその理由やメリットをしらず、アーキテクチャ自体の正当性に疑問を持ってしまいがちです。MVCでもMVVMでもMVPでも、ModelとViewは共通の存在で、もっとも重要な概念と言っても過言ではありません。しっかりと腹落ちさせておきましょう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む