Visual Studio Code で markdown のスニペットを登録する
Visual Studio Code で markdown を使用して plantuml を書くことが多いのですが、
```plantuml
@startuml
skinparam backgroundColor #FEFEFE
~
@enduml
```
というようなのを毎回手入力するのが面倒です。
何かいい方法はないかなぁと思ってたら、スニペットを使用したら解決することがわかったので、その備忘録です。
Visual Studio Code に markdown のスニペットを登録する
スニペット利用準備
私の環境では、デフォルトで markdown のスニペットが無効になっていたので、有効にします。
基本設定を開き、以下の項目をユーザー設定に追加します。
"[markdown]": { "editor.wordWrap": "on", "editor.quickSuggestions": true, "editor.snippetSuggestions": "top" }
スニペットの登録
上記のように、ユーザースニペットを選択します。
markdown
と入力します。
すると、 markdown.json
が開きます。
デフォルトでは以下のような内容になっていました。
{ // Place your snippets for markdown here. Each snippet is defined under a snippet name and has a prefix, body and // description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are: // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the // same ids are connected. // Example: // "Print to console": { // "prefix": "log", // "body": [ // "console.log('$1');", // "$2" // ], // "description": "Log output to console" // } }
これを、以下のように変更します。
{ "Plantuml": { "prefix": "plantuml", "body": [ "```plantuml", "@startuml", "skinparam backgroundColor #FEFEFE", "skinparam componentBorderColor #000000", "hide footbox", "", "@enduml", "```", ], "description": "Using PlantUML" } }
これで、markdown 編集中に p と打てば、スニペット候補が表示されるようになり、tab キーでテンプレートを挿入できるようになりました。
参考記事
Microsoft.Extensions.DependencyInjection の DI コンテナの挙動について
ASP.NET Core でよく使われる(?) Microsoft.Extensions.DependencyInjection をクラスライブラリやコンソールアプリケーションで使用したときの挙動についての備忘録です。
Microsoft.Extensions.DependencyInjection の DI コンテナの依存性の注入方法
主に以下の3パターンがあります。
AddTransient
AddScoped
AddSingleton
AddSingleton
はその名前の通りなのでいいのですが、残り2つがぱっと見わからないので、それを今回確認しました。
わかったこと
どうやら、AddTransient
と AddScoped
はスコープ設定をするかどうかで挙動がかわるみたいです。
実際に以下のように試してみました。
試したこと
まず、適当にDTOを用意します。
interface ISingleton { string Hoge { get; set; } } class Singleton : ISingleton { public Singleton() { Hoge = Guid.NewGuid().ToString(); } public string Hoge { get; set; } } interface IScoped { string Piyo { get; set; } } class Scoped : IScoped { public Scoped() { Piyo = Guid.NewGuid().ToString(); } public string Piyo { get; set; } } interface ITransient { string Fuga { get; set; } } class Transient : ITransient { public Transient() { Fuga = Guid.NewGuid().ToString(); } public string Fuga { get; set; } }
テスト用のソースとして以下を用意しました。
public void GetServiceTest() { var services = new ServiceCollection(); // 依存性の注入 services.AddSingleton<ISingleton, Singleton>(); services.AddScoped<IScoped, Scoped>(); services.AddTransient<ITransient, Transient>(); // DIコンテナの生成 var serviceProvider = services.BuildServiceProvider(); Console.WriteLine("スコープなし1回目: Singleton:" + serviceProvider.GetRequiredService<ISingleton>().Hoge); Console.WriteLine("スコープなし1回目: Scoped:" + serviceProvider.GetRequiredService<IScoped>().Piyo); Console.WriteLine("スコープなし1回目: Transient:" + serviceProvider.GetRequiredService<ITransient>().Fuga); Console.WriteLine("スコープなし2回目: Singleton:" + serviceProvider.GetRequiredService<ISingleton>().Hoge); Console.WriteLine("スコープなし2回目: Scoped:" + serviceProvider.GetRequiredService<IScoped>().Piyo); Console.WriteLine("スコープなし2回目: Transient:" + serviceProvider.GetRequiredService<ITransient>().Fuga); using (var scope = serviceProvider.CreateScope()) { Console.WriteLine("スコープあり: Singleton:" + scope.ServiceProvider.GetRequiredService<ISingleton>().Hoge); Console.WriteLine("スコープあり: Scoped:" + scope.ServiceProvider.GetRequiredService<IScoped>().Piyo); Console.WriteLine("スコープあり: Transient:" + scope.ServiceProvider.GetRequiredService<ITransient>().Fuga); } }
これを実行した結果です。
スコープなし1回目: Singleton:3a3fdfd6-50d7-4c9b-9dcf-9a316a554b06 スコープなし1回目: Scoped:f6c3fe39-b608-4083-aff5-98dc6b66b8de スコープなし1回目: Transient:b209bf1d-c83f-434a-8957-9bc528e9405c スコープなし2回目: Singleton:3a3fdfd6-50d7-4c9b-9dcf-9a316a554b06 スコープなし2回目: Scoped:f6c3fe39-b608-4083-aff5-98dc6b66b8de スコープなし2回目: Transient:84d37074-17dc-4f93-845b-4e7125361955 スコープあり: Singleton:3a3fdfd6-50d7-4c9b-9dcf-9a316a554b06 スコープあり: Scoped:990c5065-586c-4e11-b8e7-094a59c1b511 スコープあり: Transient:e10ebd8c-2f23-42c2-ba0d-7d1b2e2cb7f5
まとめ
時間がないのできなりまとめですが、以下の通りです。
ASP.NET Core では、デフォルトで以下のように動作します。
依存性の注入方法 | GetSerivece() を実行したときの振る舞い |
---|---|
AddTransient |
同一リクエストであっても、常に新しいインスタンスが生成される |
AddScoped |
同一のリクエストであれば、同じインスタンスが返ってくる。ただし、異なるリクエストならば新しいインスタンスが生成される |
AddSingleton |
異なるリクエストであっても、常に同じンスタンスが返ってくる |
コンソールアプリやクラスライブラリでは以下のように動作します。
依存性の注入方法 | GetSerivece() を実行したときの振る舞い |
---|---|
AddTransient |
常に新しいインスタンスが生成される |
AddScoped |
スコープを自身で設定する必要がある。何もスコープを設定しないときは、グローバルスコープとなり常に同じインスタンスが返ってくる |
AddSingleton |
常に同じンスタンスが返ってくる |
スコープを設定するために IServiceScopeFactory
なるものがあるらしく、自前でそれを使用することでスコープの制御ができるみたいです。
たぶんですけど、ASP.NET Core ではそのスコープ制御を隠蔽して勝手にやってくれているのだと思います。
参考サイト
Linux Mint から Windows10 へリモートデスクトップ接続する
私の環境(Linux Mint 19.1 MATE)では、標準で Windows へのリモートデスクトップができなかったので、その備忘録です。
前提
- 接続元: Linux Mint 19.1 MATE
- 接続先: Windows10
ただし、Windows10 側は Pro エディションでないとそもそもリモートデスクトップ接続を許可できません。
Home の場合、「RDP Wrapper Library」等を利用して細工する必要があります。(こちら参照)
Remmina のインストール
sudo apt-get update sudo apt-get install remmina
これで Remmina 自体は取得できるのですが、デフォルトでは SFTP と SSH のプロトコルしか対応していないので、プラグインを取得します。
sudo apt-get install remmina-plugin-rdp # なお、 VNC で接続する場合は以下もあるそうです # sudo apt-get install remmina-plugin-vnc
Remmina を使ってみる
インストール後、メニューから Remmina を起動します。
もしプラグインを入れる前に Remmina を一度でも起動している場合は、OS の再起動が必要なようです。(私の環境では、一度再起動が必要でした。)
起動後、画面左上側にある「新規」をクリックします。
そうすると、「リモートデスクトップの接続」画面が表示されますので、画面内で以下のように入力します。
- プロトコル: RDP を選択
- サーバー: Windows10 側の IP アドレス
- ユーザー名: Windows10 側のログインアカウント(マイクロソフトアカウント、つまりメールアドレスとか)
- パスワード: マイクロソフトアカウントのパスワード
それ以外は変更不要です。
これで、「接続」を押すと、私の場合は Windows10 へリモートデスクトップ接続成功しました。
参考
なお、今回はこちらの記事を参考にさせていただきました。
バッチファイルで % とかをエスケープする方法
所用で、 git log -n 1 --format=%H
をバッチファイル上で実行しようとしたのですが、うまくいかなかったので備忘録として残しておきます。
バッチファイルでは、%
は特別な意味を持つので、エスケープが必要なのはわかるのですが、何故か後ろに付ける ^
にハマりました。
結果的には以下の通りです。
git log -n 1 --format=%%^H
よくわかってませんが・・・
Fire TV Stick で IEEE802.11ac 接続できないときの対処法
仕事とは全く関係ないですが、今回の Amazon Cyber Monday にて、 Fire TV Stick を買いました。
買って、さっそくセッティングしたのですが、我が家の Wi-Fi の 11ac (5GHz 帯)のネットワークを認識しませんでした。
一応 11g は認識して、速度もフル HD で見る分には問題なかったので「まぁいっか・・・」と妥協しようと思いましたが・・・
やっぱりなんか電子レンジとかで接続が不安定になるのはシャクだし、せっかく 5GHz 帯で接続できる能力が無線 LAN ルーターにあるのにそれを持て余すのも悔しいので、ちょっと調べてみました。
ググってみたら、以下の記事がヒットしました。
チャンネルの設定が正しくないと、 5GHz 帯は接続できないようです。
ちゃんと接続するようにするには W52 の 36, 40, 44, 48 の4チャンネルのいずれかを使用する 必要があるみたいです。
無線 LAN ルーターの設定方法
で、ここからが備忘録ですが、私の家で使用している NEC の無線LANルーターでの設定方法を残しておきます。
使用している機種は「WG1200HP」というやつです。が、たぶん NEC 系ならほとんど同じかなと思います。
ルーターの管理画面で設定を行います。
変更前
変更後
「自動」になっているのを「W52」に指定してやると、無事 Fire TV Stick で 11ac が認識するようになりました。
たぶん無線 LAN ルーターの設定はいじってないはずなので、デフォルトは「自動」だと思うのですが、そのままではつながらないというのは、結構初見殺しの感じします・・・
以上、備忘録です。
ちなみに、 4k 対応の次世代 Fire TV Stick は 12/12 頃に発売みたいですね。
我が家は 4k なんてシロモノない(´;ω;`)ので、今回は安くなってる現世代を買いました。
CentOS で samba の設定をする
Windows10 から CentOS7 へエクスプローラーを使ってアクセスしたかったので、 ssamba による設定を行いました。
かなり苦戦したので、苦戦したところを備忘録として残します。
samba の準備
↑を参考にさせてもらいました。
基本的にはこの通りでよいです。
リモートデスクトップ
CentOS 上で vi でテキストファイルを編集するのはかなりキツイので、 VNC でリモートデスクトップで操作を行いました。
↑を参考にしました。 VNC でのリモートデスクトップのポート番号は 5901 です。
SELinux の無効化
こいつのせいでかなり手間取りました。
全部設定もできているはずなのに、何故か Windows からアクセスして書き込みができない・・・
いろいろググって、↓にたどり着きました。
本当は SELinux は有効にすべきなんでしょうが、今回は社内のクローズな環境に限定されていたので、無効にしてやりました。
無効にする方法は↓を参考にしました。
WPF で外部のプロジェクトからユーザーコントロールとかを参照する方法
地味にかなりハマったので、備忘録として残しておきます。
シチュエーションとしては、以下の感じです。
- プロジェクトは WPF を前提
- ユーザーコントロール(
MyUserCtrl.xaml
)を含むクラスライブラリとしてプロジェクトAがある - プロジェクトAを参照したエントリーポイント(
App.xaml
)を持つプロジェクトBがある - プロジェクトBからプロジェクトAのユーザーコントロールを呼び出す
ここで、プロジェクトAの MainWindow にて最初は単純に以下のように記述していました。
<Window x:Class="ProjectA.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ProtobufAnalyzer.DebugWpf" xmlns:pb="clr-namespace:ProjectB" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <pb:MyUserCtrl> </pb:MyUserCtrl> </Grid> </Window>
error MC3074: タグ 'MyUserCtrl' は、XML 名前空間 'clr-namespace:ProjectB' にありません。
ちゃんと xmlns:pb="clr-namespace:ProjectB"
というように名前空間を追加しているのに!
名前空間 ProjectB
に MyUserCtrl
はあるのに!
間違いなくプロジェクトBの参照にプロジェクトAを追加しているのに!
どうしろというのだ・・・
ググってもググり方が悪いのか、特に有力な情報は得られず・・・
30分以上格闘して、自分が作った過去の wpf アプリのソースを見ていたら解決策が見つかりました。(というか、過去のアプリは無意識のうちに?ちゃんとできてました)
結果的には、以下のように名前空間の後に assembly=***
を追加しなければならないようです。
<Window x:Class="ProjectA.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ProtobufAnalyzer.DebugWpf" xmlns:pb="clr-namespace:ProjectB;assembly=ProjectB" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <pb:MyUserCtrl> </pb:MyUserCtrl> </Grid> </Window>
こんなんわかるわけないやん・・・
せめてエラーとかもうちょっと直感的にわかるようなやつが出てくれれば・・・
と恨み節ですが。