テンプレートテスト
ブログの説明
ブログの説明2
menu
keyboard_arrow_up
Top
search
close
home
ホーム
computer
PC一般
construction
開発環境・ツール
code
プログラミング
home
ホーム
computer
PC一般
construction
開発環境・ツール
code
プログラミング
ラベル
C#
の投稿を表示しています。
すべての投稿を表示
ラベル
C#
の投稿を表示しています。
すべての投稿を表示
2021/02/08
image
NO IMAGE
[C#] Interlocked.CompareExchange を使って排他制御を行う
update
event_note
label
C#
排他制御を行う際、`Monitor.TryEnter` と `async/await` を使用すると上手く動作しなかったので調べていたところ、`Interlocked.CompareExchange` を使ってもっと簡単かつ安全に実装できることがわかったのでメモしておきます。
参考にしたのは以下のページです。 https://zrsbqzz4wu6limdjn6cnjegmw4--stackoverflow-com.translate.goog/questions/21410320/monitor-tryenter-doesnt-work やりたいこととしては、複数のスレッドから同時実行される可能性のある処理について、既にその処理を実行中の場合は即エラーを返したい(ロックが解放されるのを待たない)というものです。 ## サンプルコード ``` if(Interlocked.CompareExchange(ref running, 1, 0) != 0) { // ロック取得失敗 return; } try { // 時間のかかる処理 await Task.Delay(TimeSpan.FromSeconds(5)); } finally { // ロックの解放 Interlocked.Exchange(ref running, 0); } ```
## 参考 URL - https://zrsbqzz4wu6limdjn6cnjegmw4--stackoverflow-com.translate.goog/questions/21410320/monitor-tryenter-doesnt-work
Read more
2020/11/20
image
NO IMAGE
[C#] 2つのリストを結合して1つの新しいリストにする
update
event_note
label
C#
`AddRange` などでもリストの結合はできますが、片方のリストをもう片方に結合する形になるので、そうではなく、2つのリストをまとめて1つの新しいリストにする方法です。
以下のように、リストの配列を作り、`SelectMany` で平準化することで簡単にできます ``` var list1 = new[] { 1, 2, 3, 4 }; var list2 = new[] { 5, 6, 7, 8, 9 }; var newList = new[] { list1, list2 }.SelectMany(_ => _); Console.WriteLine(string.Join(",", newList)); ``` **出力結果** ```sh 1,2,3,4,5,6,7,8,9 ```
## 参考 URL
Read more
2020/11/19
image
NO IMAGE
[C#] 配列やリストが昇順 or 降順になっているかどうかを調べる
update
event_note
label
C#
`OrderBy` と `SequenceEqual` を使えば簡単にできます。
```cs list.OrderBy(x => x).SequenceEqual(list) ``` 降順の場合は `OrderByDescending` を使います。
## 参考 URL - https://stackoverflow.com/questions/23562150/linq-expression-to-validate-if-list-is-ordered-ascending-or-descending/23562239 - https://stackoverflow.com/questions/1940214/how-to-check-if-a-list-is-ordered
Read more
2020/10/09
image
NO IMAGE
[ASP.NET Core] Form value count limit 1024 exceeded のエラーが発生した
update
event_note
label
ASP.NET Core
label
C#
`form` で `submit` した際に `Form value count limit 1024 exceeded` のエラーが表示されました。
フォームで送信する値の数が上限である 1024 を超えたために発生したようです。 ## 環境 - Visual Studio 2017 - .NET Core 2.2 ## 対処方法 フォームで 1024 以上も値を送るような設計がそもそもおかしいとか、いろいろあるとは思いますが、とりあえず上限を変更することで対応可能です。 Post を受け取る Controller に `RequestFormLimits` の属性を追加することで上限は簡単に変更できます。 ```cs [HttpPost] [RequestFormLimits(ValueCountLimit = 2048)] public IActionResult Index(Hoge hoge) { // Do something } ```
## 参考 URL - https://www.366service.com/jp/qa/0b21184f67097eff65ca439f3a833ec6
Read more
2020/08/20
image
NO IMAGE
[C#] 文字の Unicode を取得
update
event_note
label
C#
文字の Unicode を取得する方法です。意外と情報が見つからなかったので。
```cs using System; using System.Text; using System.Globalization; ``` ```cs var unicode = new UnicodeEncoding(true, false); var encodedBytes = unicode.GetBytes("あ"); string output = ""; for (int i = 0; i < encodedBytes.Length; i++) { output += string.Format("{0:x2}", encodedBytes[i]); } Console.WriteLine(output);// 3042 // 数値に変換 var hex = int.Parse(output, NumberStyles.HexNumber); Console.WriteLine(hex.ToString());// 12354 ``` `あ` の Unicode は以下です。 - https://0g0.org/unicode/3042/
## 参考 URL - https://www.ipentec.com/document/csharp-unicode-string-to-unicode-scalar-value-string
Read more
2020/07/30
image
NO IMAGE
[C#] コンパイラが必要とするメンバー 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create' がありません
update
event_note
label
C#
`dynamic` 型を使用した場合に以下のようなエラーが表示されました。
```sh コンパイラが必要とするメンバー 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create' がありません ``` ググってみると、`Microsoft.CSharp.dll` への参照を追加すればよいとの情報を得ましたが、見つからず。 どうやら .NET Standard のクラスライブラリの場合は、NuGet で以下の2つを追加する必要があるみたいです。 - System.Dynamic.Runtime - Microsoft.CSharp
## 参考 URL - http://var.blog.jp/archives/68140817.html - http://mag.autumn.org/Content.modf?id=20190124151720
Read more
2020/07/17
image
NO IMAGE
[C#] Stream に対して ReadAllLines を行いたい
update
event_note
label
C#
`File` クラスには `ReadAllLines` というメソッドがありますが、`Stream` にはないので、同等の機能を実装してみます。
## 環境 - Visual Studio 2017 - .NET Core 2.2 - C# 7.1 ## サンプルコード ```cs IEnumerable
ReadAllLines(Stream stream) { var lines = new List
(); using (var sr = new StreamReader(stream)) { while (sr.Peek() >= 0) lines.Add(sr.ReadLine()); } return lines; } ``` 反復子を使うともうちょっとシンプルになります。 ```cs IEnumerable
ReadAllLines(Stream stream) { using (var sr = new StreamReader(stream)) { while (sr.Peek() >= 0) yield return sr.ReadLine()); } } ``` 非同期版です。 ```cs async Task
> ReadAllLinesAsync(Stream stream) { var lines = new List
(); using (var sr = new StreamReader(stream)) { while (sr.Peek() >= 0) lines.Add(await sr.ReadLineAsync()); } return lines; } ``` C# 8.0 以降であれば `async/await` と `yield` が共存できるそうなので、もっとシンプルになります。 あとは、これらは拡張メソッドにしておいたほうが使い勝手が良いかもしれません。
## 参考 URL - https://stackoverflow.com/questions/13312906/readalllines-for-a-stream-object
Read more
2020/07/13
image
NO IMAGE
[C#] コンストラクタで base と this を両方使いたい
update
event_note
label
C#
コンストラクタにおいて、基底クラスのコンストラクタを指定したい場合は `base` を、同じクラス内の別のコンストラクタを指定したい場合は `this` を指定しますが、両方指定したい場合はどうすればいいのか?
結論から先に書くと、両方を指定することはできません。 恐らくですが、`base` と `this` を両方指定したいと思うということは、コンストラクタ内で行う処理を全て共通化したいということなのだと思います。 私の場合はそうでした。 そして、私の場合はデフォルト引数を使うことで解決しました。 また、`base` や `this` を指定した場合(または指定しなかった場合)に、どのようにコンストラクタが呼ばれるかをきちんと把握すれば、もしかしたらどちらかを指定するだけで事足りるかもしれません。 というわけでいろいろ試してみました。 ## 環境 - Visual Studio 2019 - .NET Core 3.1 ## サンプル1 基底クラス `SampleBase` と、派生クラス `Sample` に、それぞれ引数なしと引数ありのコンストラクタを作成しています。 ### パターン1 `base` も `this` も指定しない場合です。 ```cs public static void Main() { new Sample(); Console.WriteLine("----------"); new Sample("foo"); } ///
/// 基底クラス ///
abstract class SampleBase { public SampleBase() { Console.WriteLine("SampleBase コンストラクタ引数なし"); } public SampleBase(string foo) { Console.WriteLine($"SampleBase コンストラクタ引数あり:{foo}"); } } ///
/// 派生クラス ///
class Sample : SampleBase { public Sample() { Console.WriteLine("Sample コンストラクタ引数なし"); } public Sample(string foo) { Console.WriteLine($"Sample コンストラクタ引数あり:{foo}"); } } ``` **出力結果** ```sh SampleBase コンストラクタ引数なし Sample コンストラクタ引数なし ---------- SampleBase コンストラクタ引数なし Sample コンストラクタ引数あり:foo ``` 派生クラス `Sample` は引数の有無によって呼ばれるコンストラクタが違いますが、基底クラス `SampleBase` はいずれの場合も引数なしのコンストラクタが呼ばれています。 ### パターン2 パターン1をベースに、基底クラスの引数ありコンストラクタを使うために、派生クラス `Sample` で `base` を指定しています。 ```cs public static void Main() { new Sample(); Console.WriteLine("----------"); new Sample("foo"); } ///
/// 基底クラス ///
abstract class SampleBase { public SampleBase() { Console.WriteLine("SampleBase コンストラクタ引数なし"); } public SampleBase(string foo) { Console.WriteLine($"SampleBase コンストラクタ引数あり:{foo}"); } } ///
/// 派生クラス ///
class Sample : SampleBase { public Sample() { Console.WriteLine("Sample コンストラクタ引数なし"); } public Sample(string foo) : base(foo) { Console.WriteLine($"Sample コンストラクタ引数あり:{foo}"); } } ``` **出力結果** ```sh SampleBase コンストラクタ引数なし Sample コンストラクタ引数なし ---------- SampleBase コンストラクタ引数あり:foo Sample コンストラクタ引数あり:foo ``` 引数を指定しなかった場合は、`Sample` `SampleBase` ともに引数なしのコンストラクタがコールされます。 引数を指定した場合は、`Sample` `SampleBase` ともに引数ありのコンストラクタがコールされます。 まぁここらへんまでは当たり前ですね。 ### パターン3 パターン2をベースに、基底クラス `SampleBase` の引数ありコンストラクタで `this` を指定しています。 ```cs public static void Main() { new Sample(); Console.WriteLine("----------"); new Sample("foo"); } ///
/// 基底クラス ///
abstract class SampleBase { public SampleBase() { Console.WriteLine("SampleBase コンストラクタ引数なし"); } public SampleBase(string foo) : this() { Console.WriteLine($"SampleBase コンストラクタ引数あり:{foo}"); } } ///
/// 派生クラス ///
class Sample : SampleBase { public Sample() { Console.WriteLine("Sample コンストラクタ引数なし"); } public Sample(string foo) : base(foo) { Console.WriteLine($"Sample コンストラクタ引数あり:{foo}"); } } ``` **出力結果** ```sh SampleBase コンストラクタ引数なし Sample コンストラクタ引数なし ---------- SampleBase コンストラクタ引数なし SampleBase コンストラクタ引数あり:foo Sample コンストラクタ引数あり:foo ``` 引数を指定した場合、基底クラスのコンストラクタは両方呼ばれます。 ### パターン4 パターン3をベースに、派生クラス `Sample` の引数なしコンストラクタで基底クラス `SampleBase` の引数ありコンストラクタを呼んでいます。 ```cs public static void Main() { new Sample(); Console.WriteLine("----------"); new Sample("foo"); } ///
/// 基底クラス ///
abstract class SampleBase { public SampleBase() { Console.WriteLine("SampleBase コンストラクタ引数なし"); } public SampleBase(string foo) : this() { Console.WriteLine($"SampleBase コンストラクタ引数あり:{foo}"); } } ///
/// 派生クラス ///
class Sample : SampleBase { public Sample() : base(null) { Console.WriteLine("Sample コンストラクタ引数なし"); } public Sample(string foo) : this() { Console.WriteLine($"Sample コンストラクタ引数あり:{foo}"); } } ``` **出力結果** ```sh SampleBase コンストラクタ引数なし SampleBase コンストラクタ引数あり: Sample コンストラクタ引数なし ---------- SampleBase コンストラクタ引数なし SampleBase コンストラクタ引数あり: Sample コンストラクタ引数なし Sample コンストラクタ引数あり:foo ``` 引数を指定した場合は全てのコンストラクタが呼ばれています。 多分これが一番問題のパターン。 派生クラス `Sample` の引数の値を基底クラス `SampleBase` に渡しつつ、コンストラクタ内の処理は各クラスの引数なしコンストラクタに集約したい。 しかし、派生クラス `Sample` の引数ありコンストラクタで `base` と `this` の両方を指定することはできません。 かと言って、このパターンのようにやると `this` を指定したときに引数の情報が失われてしまいます(当たり前ですが)。 というわけで、代替案が次のサンプルです。 ## サンプル2(代替案) 派生クラス `Sample` のコンストラクタを引数ありの1つのみにし、デフォルト引数を定義する方法です。 ```cs public static void Main() { new Sample(); Console.WriteLine("----------"); new Sample("foo"); } ///
/// 基底クラス ///
abstract class SampleBase { public SampleBase() { Console.WriteLine("SampleBase コンストラクタ引数なし"); } public SampleBase(string foo) : this() { Console.WriteLine($"SampleBase コンストラクタ引数あり:{foo}"); } } ///
/// 派生クラス ///
class Sample : SampleBase { public Sample(string foo = null) : base(foo) { Console.WriteLine($"Sample コンストラクタ引数あり:{foo}"); } } ``` **出力結果** ```sh SampleBase コンストラクタ引数なし SampleBase コンストラクタ引数あり: Sample コンストラクタ引数あり: ---------- SampleBase コンストラクタ引数なし SampleBase コンストラクタ引数あり:foo Sample コンストラクタ引数あり:foo ``` 私の場合はこれで解決しました。
Read more
2020/07/02
image
NO IMAGE
[C#] xUnit で MemberData を使ったテストがテストエクスプローラーで1つのテストとして表示される
update
event_note
label
C#
label
xUnit
`xUnit` で `MemberData` や `ClassData` を使ってテストケースを作成した場合、 Visual Studio のテストエクスプローラーでは複数のテストケースが単一のテストケースとして表示されてしまいます。
これだとデバッグが非常にやりにくいので、`InlineData` と同じように複数のテストケースとして表示する方法がないか調べてみると、以下の記事が見つかりました。 - https://stackoverflow.com/questions/30574322/memberdata-tests-show-up-as-one-test-instead-of-many Visual Studio のテストエクスプローラーで各テストケースを別々の項目として表示するためには、テストケースの型に `IXunitSerializable` を実装する必要があるみたいです。 ## 環境 - Visual Studio 2017 - .NET Core 2.2 - xUnit 2.4.1 ## サンプル ### 変更前 例えば、`MemberData` を使ったテストコードは以下のような感じになっていると思います。 ```cs [Theory, MemberData(nameof(TestData))] public void TestMethod(int param1, string param2) { // Do something test } public static IEnumerable
TestData() { yield return new object[] { 0, "hoge" }; yield return new object[] { 1, "fuga" }; } ``` ### 変更後 `IXunitSerializable` を実装するためにテストデータクラス `TestCaseData` を作成します。 ```cs [Theory, MemberData(nameof(TestData))] public void TestMethod(TestCaseData testCaseData) { var param1 = testCaseData.Param1; var param2 = testCaseData.Param2; // Do something test } public class TestCaseData : IXunitSerializable { public int Param1 { get; set; } public string Param2 { get; set; } public void Serialize(IXunitSerializationInfo info) { info.AddValue(nameof(Param1), Param1.ToString()); info.AddValue(nameof(Param2), Param2.ToString()); } public void Deserialize(IXunitSerializationInfo info) { } } public static IEnumerable
TestData() { yield return new object[] { new TestCaseData{ Param1 = 0, Param2 = "hoge" } }; yield return new object[] { new TestCaseData{ Param1 = 1, Param2 = "fuga" } }; } ``` 結構面倒です。 ## もう少し汎用的になるように改良してみる 上記のままだと、テストケースの度に `IXunitSerializable` を実装する必要があり面倒なので、何とかして共通化できないかと思い、とりあえず以下の2案が思い浮かびました。 ### ジェネリックを使って汎用的に実装する `IXunitSerializable` を実装した `ValidateTestCase` を作成し、ジェネリックでテストケースクラスの型を指定してやります。 ```cs [Theory, MemberData(nameof(TestData))] public void TestMethod(ValidateTestCase
testCaseData) { var param1 = testCaseData.Param.Param1; var param2 = testCaseData.Param.Param2; // Do something test } public class ValidateTestCase
: IXunitSerializable { public T Param { get; set; } public void Serialize(IXunitSerializationInfo info) { // JSON を使う場合 info.AddValue(nameof(Param), JsonConvert.SerializeObject(Param)); // ハッシュ値を使う場合 // info.AddValue(nameof(Param), GetHashCode()); // GUID を使う場合 // info.AddValue(nameof(Param), Guid.NewGuid().ToString()); } public void Deserialize(IXunitSerializationInfo info) { } } public class TestCaseData { public int Param1 { get; set; } public string Param2 { get; set; } } public static IEnumerable
TestData() { yield return new object[] { new ValidateTestCase
{ Param = new TestCaseData(){ Param1 = 0, Param2 = "hoge" } } }; yield return new object[] { new ValidateTestCase
{ Param = new TestCaseData(){ Param1 = 1, Param2 = "fuga" } } }; } ``` `Serialize` メソッドで登録する文字列を `ToString()` から JSON でのシリアライズに変更しているのがポイントです。 クラスに対して `ToString()` するとクラス名が出力されるので、全てのテストで同じ文字列になってしまい、テストエクスプローラーでは単一のテストとして表示されてしまいました。 この文字列は一連のテストケースにおいてユニークでないとダメなようです。 なので、テストパラメーターには重複はないという前提で、JSON でシリアライズしてみました。 ただし、テストケースクラス `TestCaseData` にデリゲートを含んでいる場合は上手くいかなかったので、そういう場合はハッシュ値や GUID などを使ったほうが良いと思います。 (ハッシュ値は被ることもあるかもしれないので、GUID のほうが確実か?) ### 抽象クラスを作成して汎用的に実装する 上記だと毎回 `ValidateTestCase` と `T` の2つのクラスをインスタンス化しないといけなくてちょっと面倒なので、同じような感じで抽象クラスで実装してみました。 自クラス `this` に対してシリアライズを行っています。 ```cs [Theory, MemberData(nameof(TestData))] public void TestMethod(TestCaseData testCaseData) { var param1 = testCaseData.Param1; var param2 = testCaseData.Param2; // Do something test } public abstract class XunitSerializableBase : IXunitSerializable { public void Serialize(IXunitSerializationInfo info) { // JSON を使う場合 info.AddValue(nameof(XunitSerializableBase), JsonConvert.SerializeObject(Param)); // ハッシュ値を使う場合 // info.AddValue(nameof(XunitSerializableBase), GetHashCode()); // GUID を使う場合 // info.AddValue(nameof(XunitSerializableBase), Guid.NewGuid().ToString()); } public void Deserialize(IXunitSerializationInfo info) { } } public class TestCaseData : XunitSerializableBase { public int Param1 { get; set; } public string Param2 { get; set; } } public static IEnumerable
TestData() { yield return new object[] { new TestCaseData{ Param1 = 0, Param2 = "hoge" } }; yield return new object[] { new TestCaseData{ Param1 = 1, Param2 = "fuga" } }; } ``` ちょっとだけ記述量が減りました。 ## 他の案は? 上記のリンク先にある `DjvuTheory` が便利そうだったので試しましたが、.NET Core 2.2 だと動きませんでした。 自分で修正しようともしてみましたが、何故かうまくいかず断念。 これが使えたら `Theory` を`DjvuTheory` に置換するだけでいけそうだったのに残念です。
## 参考 URL - https://stackoverflow.com/questions/30574322/memberdata-tests-show-up-as-one-test-instead-of-many - https://darchuk.net/2019/04/12/serializing-xunit-test-cases/ - https://docs.microsoft.com/ja-jp/azure/bot-service/unit-test-bots?view=azure-bot-service-4.0&tabs=csharp - https://github.com/mysteryx93/XunitDjvuTheory
Read more
2020/06/26
image
NO IMAGE
[C#] ClassData でテストデータを作成する際に、テストクラス内のリソースにアクセスしたい
update
event_note
label
C#
label
xUnit
`xUnit` で複雑なテストデータを作成する場合、`ClassData` を使って別途テストデータ作成用のクラスを用意したりしますが、このテストデータ作成用のクラスでテストクラス内のリソースを操作したいことがあったので、思いついた案を載せておきます。
ここでいうリソースとは、例えばテスト用のデータベースだとか、外部ファイルなどです。 あくまで私が思いついた一例ですが、概要としては、以下です。 - テストメソッドの引数にデリゲートを用意し、テストメソッド内からリソースを渡す - テストデータ作成用のクラスで、リソースに対する処理を記述 ## 環境 - Visual Studio 2017 - .NET Core 2.2 ## サンプルコード `resource` がデータベースなどの外部のリソースを想定しています。 ### テスト対象のクラス 以下のようなクラスをテストしたいとします。 ```cs // テストしたいクラス public class Target { // テストしたいメソッド public int Add(IList
resource) { // 例えば、データベースなどから値を読み込んで、何か処理をした値を返すなど // ここでは全レコードを読み込んで総和を返すようなことを想定 return resource.Sum(); } } ``` ### テストコード 以下がテストコードです。 解説はコメントに書いてある通りです。 ```cs using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Xunit; using Xunit.Abstractions; namespace TestProject { // テストを行うクラス public class TestClass { ITestOutputHelper output; Target target; readonly IList
resource;// 例えば、データベースやファイルなどの外部リソース public TestClass(ITestOutputHelper output) { // デバッグ用にテストエクスプローラーに出力できるようにしておく this.output = output; // リソースの初期化(実際には IClassFixture を使うなどする) resource = new List
{ 1, 2 }; // テストクラスのインスタンスを作成 target = new Target(); } [Theory, ClassData(typeof(TestData))] public void TestMethod( // テスト前にリソースに対して行う処理(戻り値が必要なら Func にする) Action
> action, // テスト実行後の期待値 int expected ) { // テストに必要な前処理を行う action(resource); // デバッグ用にテスト前のリソースの状態を出力 output.WriteLine($"resource: {string.Join(", ", resource)}"); // テストの実行 var result = target.Add(resource); // デバッグ用に結果を出力 output.WriteLine($"result: {result.ToString()}"); // 結果の確認 Assert.Equal(expected, result); } } // テストデータを作成するクラス class TestData : IEnumerable
{ List
_testData = new List
(); public TestData() { // いくつかのパターンでテストデータを作成してみる // テストケース1(リソースの中身を書き換え) Action
> action = resource => { resource[0] = 1; resource[1] = 2; }; _testData.Add(new object[] { action, 3 }); // テストケース2(リソースに要素を追加) _testData.Add(new object[] { new Action
>(resource => resource.Add(3)), 6 }); // テストケース3(リソースをクリア) action = resource => resource.Clear(); _testData.Add(new object[] { action, 0 }); } public IEnumerator
GetEnumerator() => _testData.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } } ``` ### 実行結果 **テストケース1** ```sh resource: 1, 2 result: 3 ``` **テストケース2** ```sh resource: 1, 2, 3 result: 6 ``` **テストケース3** ```sh resource: result: 0 ```
## 参考 URL
Read more
2020/06/25
image
NO IMAGE
[C#] nameof 演算子の代わりにフルネームを返すメソッドを作る
update
event_note
label
C#
`nameof` 演算子は最後の名前しか返しませんが、フルネームを取得したいことは多々あります。 そんななか、stack overflow に便利そうなコードがあったので、そのまま転載します。
- https://stackoverflow.com/questions/27898178/why-does-nameof-return-only-last-name 例えば、以下のようなクラスがあったとして、 ```cs class SpeciesFamily { public string Name { get; set; } } class Species { public SpeciesFamily Family { get; set; } public string Name { get; set; } } class Cat { public Species Species { get; set; } } ``` `Species.Family.Name` という文字列を `nameof` 演算子を使って取得しようとすると、以下のようなコードになってしまいます。 ```cs var fullName = $"{nameof(Species)}.{nameof(Species.Family)}.{nameof(SpeciesFamily.Name)}" ``` 同じクラス名やプロパティ名を何度も書くことになるので、階層が深くなればなるほど面倒です。 これに対して、フルネームを簡単に取得できるようにしたメソッドのサンプルが以下の2つです。 (階層が浅いと記述量はあまり変わりませんが・・・) ## サンプルコード1 ```cs public static string GetMemberString
(System.Linq.Expressions.Expression
> member) { if (member == null) { throw new ArgumentNullException("member"); } var propertyRefExpr = member.Body; var memberExpr = propertyRefExpr as System.Linq.Expressions.MemberExpression; if (memberExpr == null) { var unaryExpr = propertyRefExpr as System.Linq.Expressions.UnaryExpression; if (unaryExpr != null && unaryExpr.NodeType == System.Linq.Expressions.ExpressionType.Convert) { memberExpr = unaryExpr.Operand as System.Linq.Expressions.MemberExpression; if (memberExpr != null) { return memberExpr.Member.Name; } } } else { //gets something line "m.Field1.Field2.Field3", from here we just remove the prefix "m." string body = member.Body.ToString(); return body.Substring(body.IndexOf('.') + 1); } throw new ArgumentException("No property reference expression was found.", "member"); } ``` **使い方** ```cs // Will return a string containing "Species.Family.Name". var fullName = GetMemberString
(x => x.Species.Family.Name) ``` ## サンプルコード2 ```cs public static class NameOf
{ #region Public Methods public static string Full(Expression
> expression) { var memberExpression = expression.Body as MemberExpression; if (memberExpression == null) { if (expression.Body is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.Convert) memberExpression = unaryExpression.Operand as MemberExpression; } var result = memberExpression.ToString(); result = result.Substring(result.IndexOf('.') + 1); return result; } public static string Full(string sourceFieldName, Expression
> expression) { var result = Full(expression); result = string.IsNullOrEmpty(sourceFieldName) ? result : sourceFieldName + "." + result; return result; } #endregion } ``` **使い方** ```cs // Will return a string containing "Species.Family.Name". var fullName = NameOf
.Full(c => c.Species.Family.Name); // Will return a string containing "cat.Species.Name". var fullNameWithPrefix = NameOf
.Full("cat", c => c.Species.Name); ``` `"cat"` のようにプレフィックスが指定できるので、こちらのほうがより汎用的かと思います。 また、`"cat"` の部分も `nameof` 演算子を使えば、文字列の記述を完全に無くすことができます。
## 参考 URL - https://stackoverflow.com/questions/27898178/why-does-nameof-return-only-last-name
Read more
2020/06/24
image
NO IMAGE
[ASP.NET Core] ModelState のチェックを無効化
update
event_note
label
ASP.NET Core
label
C#
ASP.NET Core において、`[Required]` などといった Attribute によるモデルのチェックを無効化する方法です。
## 環境 - Visual Studio 2017 - ASP.NET Core 2.2 ## サンプルコード `Remove` メソッドでチェックを無効化したいプロパティのキーを指定します。 ```cs ModelState.Remove("hoge"); ``` 全てのプロパティに対するチェックを無効化したい場合は、以下のようにして全てのキーを削除すれば OK です。 ```cs foreach (var key in ModelState.Keys) { ModelState.Remove(key); } ``` `Remove` メソッドでキーを削除したら、`ModelState.IsValid` の値も自動で更新されるようです。
## 参考 URL
Read more
2020/06/23
image
NO IMAGE
[C#] Null 許容型かどうかを判別する
update
event_note
label
C#
どのように判定するかは目的や用途に応じて変わりそうですが、あくまで例としてサンプルを作成してみました。
## 環境 - Visual Studio 2017 - .NET Core 2.2 ## サンプルコード ```cs public static void Main() { var personClass = new PersonClass(); var personStruct = new PersonStruct(); var persons = new List
(); IsNullable(typeof(int));// False IsNullable(typeof(int?));// True IsNullable(typeof(PersonClass));// True IsNullable(typeof(PersonStruct));// False IsNullable(personClass.GetType());// True IsNullable(personClass.Age.GetType());// False IsNullable(personClass.Name?.GetType());// True IsNullable(personStruct.GetType());// False IsNullable(personStruct.Age.GetType());// False IsNullable(personStruct.Name?.GetType());// True IsNullable(typeof(List<>));// True IsNullable(persons.GetType());// True } static bool IsNullable(Type type) { var ret = type == null || // Null条件演算子用にこの条件を入れているだけなので、場合によっては不要 !type.IsValueType || // 値型でない -> Nullable Nullable.GetUnderlyingType(type) != null;// 非Null許容型が取得できる -> Null許容演算子が指定されている -> Nullable Console.WriteLine(ret);// デバッグ用に表示 return ret; } public class PersonClass { public int Age { get; set; } public string Name { get; set; } } public struct PersonStruct { public int Age { get; set; } public string Name { get; set; } } ``` 間違いや他に良い方法があれば教えてください。
## 参考 URL - https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/builtin-types/nullable-value-types#how-to-identify-a-nullable-value-type - https://docs.microsoft.com/ja-jp/dotnet/api/system.nullable.getunderlyingtype - https://docs.microsoft.com/ja-jp/dotnet/api/system.type.isvaluetype
Read more
2020/06/19
image
NO IMAGE
[C#] 非同期メソッドのモック
update
event_note
label
C#
非同期メソッド (`async / await`) の戻り値は `Task` なので、`Moq` を使う場合にも `Task` を返す必要があります。
この場合、モックでは `Task.FromResult` を使って戻り値を返すようにします。 以下サンプルです。 **非同期メソッドでない場合** ```cs sample = new Mock
(); sample.Setup(x => x.Hoge(It.IsAny
())).Returns(true); ``` **非同期メソッドの場合** ```cs sample = new Mock
(); sample.Setup(x => x.HogeAsync(It.IsAny
())).Returns(Task.FromResult(true)); ```
## 参考 URL - https://stackoverflow.com/questions/21253523/how-can-i-tell-moq-to-return-a-task - https://qiita.com/TsuyoshiUshio@github/items/37d1cee9118d681db5af
Read more
2020/06/18
image
NO IMAGE
[C#] リストをデシリアライズしたときに項目が追加登録されてしまう
update
event_note
label
C#
リストの初期値が設定されているクラスのデータを Newtonsoft.Json (Json.NET) でデシリアライズすると、そのリストの項目は初期値を含んだうえでデシリアライズされた値が追加登録されていました。 シリアライズされた内容とデシリアライズされた内容が異なるので、いや、ほんとはまりました。
## 環境 - Visual Studio 2017 - .NET Core 2.2 ## サンプルコード 以下のようなクラスをシリアライズ、デシリアライズするとします。 ```cs public class SampleData { public IList
Hoge { get; set; } = new List
{ 1 }; } ``` ```cs var data = new SampleData(); // シリアライズ var serialized = JsonConvert.SerializeObject(data); Console.WriteLine(serialized); // デシリアライズ(このタイミングでリストの項目が2つになっている!) var deserialized = JsonConvert.DeserializeObject
(serialized); Console.WriteLine($"Hoge Count: {deserialized.Hoge.Count()}"); // もう一度シリアライズして確認 var serialized2 = JsonConvert.SerializeObject(deserialized); Console.WriteLine(serialized2); ``` **出力結果** ```bat {"Hoge":[1]} Hoge Count: 2 {"Hoge":[1,1]} ``` デシリアライズ時に項目が1つ増えています。 シリアライズした内容はリストを置換するではなく、リストに追加登録されるからです。 いや、これほんとにはまった。 ## ObjectCreationHandling.Replace を指定する 初期値を含めないようにするにはデシリアライズ時のオプションで `ObjectCreationHandling.Replace` を指定する必要があります。 ```cs var deserialized = JsonConvert.DeserializeObject
(serialized, new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace, }); ``` こちらの動作のほうが直観的だと思うので、こちらが既定値のほうが良いと思うのですが、私だけでしょうか? ちなみに `DataContractJsonSerializer` を使った場合は既定で置換してくれました。
## 参考 URL - https://stackoverflow.com/questions/46300616/json-net-deserialize-with-collection-initialization-in-constructor?noredirect=1&lq=1 - https://ja.coder.work/so/c%23/821888
Read more
2020/06/17
image
NO IMAGE
[C#] DateTime 型を含むデータのシリアライズ
update
event_note
label
C#
DateTime 型を含むデータを Microsoft 標準の `DataContractJsonSerializer` を使ってシリアライズすると例外が発生しました。
## 環境 - Visual Studio 2017 - .NET Core 2.2 ## サンプルコード 以下のようなクラスをシリアライズしたいとします。 ```cs public class Person { public DateTime Birth { get; set; } = DateTime.Today; public string Name { get; set; } = "Name"; public int Age { get; set; } = 20; } ``` `DataContractJsonSerializer` を使ってシリアライズしてみます。 ```cs static public string Serialize
(T value) { var serializer = new DataContractJsonSerializer(typeof(T)); var serializedData = string.Empty; using (var memoryStream = new MemoryStream()) { serializer.WriteObject(memoryStream, value); serializedData = Encoding.UTF8.GetString(memoryStream.ToArray()); } return serializedData; } ``` ```cs var data = new Person(); var serialized = Serialize(data); Console.WriteLine(serialized); ``` **出力結果** ```bat {"Age":20,"Birth":"\/Date(1592319600000+0900)\/","Name":"Name"} ``` ### 例外が発生するパターン ここで、上記の `DateTime` 型である `Birth` の初期値を未設定にすると、`DateTime.MinValue` が初期値になりますが、この場合に以下の例外が発生します。 ```bat System.Runtime.Serialization.SerializationException : DateTime values that are greater than DateTime.MaxValue or smaller than DateTime.MinValue when converted to UTC cannot be serialized to JSON. ---- System.ArgumentOutOfRangeException : Specified argument was out of the range of valid values. ``` `DataContractJsonSerializer` は `DateTime` を UTC に変換してシリアライズしようとしますが、MinValueだった場合、JST だと -9 時間することになるので、アンダーフローを起こすのが原因らしいです。 ## 対処方法 とりあえず思いついたのは以下です。 ### その1 DateTimeOffset を使う 型を変更できるなら `DateTimeOffset` に変更すればシリアライズ可能になります。 ### その2 他のパーサーを使う 例えば、Newtonsoft.Json を使うと `DateTime` が `MinValue` であっても以下のように ISO 形式で文字列に変換されるため、シリアライズ可能です。 ```cs var data = new Person(); var serialized = JsonConvert.SerializeObject(data); Console.WriteLine(serialized); ``` **出力結果** ```bat {"Birth":"0001-01-01T00:00:00","Name":"Name","Age":20} ```
## 参考 URL - https://qiita.com/Toraja/items/d0c5ada821df81de2440
Read more
2020/05/21
image
NO IMAGE
Moq で System.NotSupportedException : Unsupported expression のエラーが表示された
update
event_note
label
C#
Moq を使ってテストコードを書いているときに、以下のようなエラーが表示されました。
```sh Message: System.NotSupportedException : Unsupported expression ``` 私の場合、モックしようとしているメソッドに `virtual` を付けると解決しました。
## 参考 URL - https://github.com/moq/moq4/issues/961
Read more
2020/04/27
image
NO IMAGE
[C#] 文字列内の文字が全て同じかどうかをチェックする
update
event_note
label
C#
例えば `99999` や `aaaa` など、文字列内の文字が全て同じかどうかを簡単にチェックする方法です。
まず、単純に同じ文字かどうかだけを判定するなら、Linq を使えば一発です。 ```cs var str = "99999"; Console.WriteLine(str.Distinct().Count() == 1);// True ``` 重複を排除した結果、要素数が1つだけになっていれば全て同じ文字と判断できます。 特定の文字の場合のみ、文字列内が全て同じ文字かどうかを判定したいなら、フィルタリングする必要があります。 ``` var str1 = "00000"; var str2 = "00999"; var str3 = "99999"; // 文字が全て 9 の場合のみ True にしたい Console.WriteLine(!str1.Any(x => x != '9') && str1.Distinct().Count() == 1);// False Console.WriteLine(!str2.Any(x => x != '9') && str2.Distinct().Count() == 1);// False Console.WriteLine(!str3.Any(x => x != '9') && str3.Distinct().Count() == 1);// True ``` - `9` 以外の文字を抽出した結果、要素数が 0 だったならば `9` 以外の文字が含まれていない - 重複を排除した結果、要素数が1つだけになっていれば全て同じ文字 この2つの条件で判断できます。 コード自体は短いですが、毎回これを書くのも面倒なので、拡張メソッドでも作成しておくと便利かと思います。 もっと簡単に判別できる方法があれば教えてください。
## 参考 URL - https://teratail.com/questions/140064
Read more
2020/04/15
image
NO IMAGE
[C#] バイト配列のシリアライズ
update
event_note
label
C#
Newtonsoft.json でバイト配列をシリアライズすると、BASE64 にエンコードされて出力されてしまいます。
```cs var foo = new Foo { Data = new byte[] { 0x48, 0x49, 0x1d, 0x52, 0x53, 0x1d, 0x56, 0x57, 0x00 } }; var json = JsonConvert.SerializeObject(foo); Console.WriteLine(json); ``` ```cs public class Foo { public byte[] Data { get; set; } } ``` **出力結果** ```sh {"Data":"SEkdUlMdVlcA"} ``` 個人的には以下のように出力されることを期待していました。 ```cs {"Data":[48, 49, 1D, 52, 53, 1D, 56, 57, 00]} ``` ## 解決策 配列ではなくリストを使うと解決されるという記事を見て、上記のコードを変更したら期待した出力になりました。 しかし、他のケースではリストでも BASE64 で出力される場合があったりしたので、素直に `int` に変更しました。
## 参考 URL - https://www.newtonsoft.com/json/help/html/SerializationGuide.htm - https://stackoverflow.com/questions/55153522/why-does-newtonsoft-json-serializes-byte-as-base64-but-sbyte-not
Read more
2020/04/03
image
NO IMAGE
[ASP.NET Core] TempData を使っている場合のテストコードの書き方
update
event_note
label
ASP.NET Core
label
C#
Moq を使って TempData の Mock を作成してテストコードを書く方法です。
`TempDataDictionaryFactory` を使って `TempData` を作成して、Controller に渡します。 ```cs var tempDataDictionaryFactory = new TempDataDictionaryFactory(Mock.Of
()); var tempData = tempDataDictionaryFactory.GetTempData(new DefaultHttpContext()); var controller = new ShokiSetteiController(shiyouSetteiCreator, httpContextAccessor.Object, messageLocalizer.Object, wordLocalizer.Object) { TempData = tempData, }; ```
## 参考 URL - https://stackoverflow.com/questions/55914515/how-to-test-controller-method-that-use-tempdata-in-asp-mvc-core - https://stackoverflow.com/questions/52181767/mocking-a-tempdata-in-asp-net-core-in-mstest
Read more
前の投稿
ホーム
Translate
Popular Posts
ASP.NET Core で AdminLTE を使用する
TortoiseGit でコミットメッセージを変更する
image
NO IMAGE
TestLink で LDAP 認証を行う
image
NO IMAGE
[C#] Dictionary の キーがタプルの場合に JSON へのシリアライズとデシリアライズを行う方法
TortoiseGit でリモートリポジトリのタグを削除する
image
NO IMAGE
[C#] SonarQube で .NET アプリケーションのコード解析を行う
GitLab をアップグレードしたら Redmine へのリンクが解除された
image
NO IMAGE
ASP.NET Core (.NET Core) でバックグランドタスクを起動する
GitBucketのrootのパスワードを忘れたので再設定する
image
NO IMAGE
TortoiseGit のコンテキストメニューが消える
Labels
.NET Core
31
.NET Framework
17
.NET Standard
2
AdminLTE
1
Apache
3
AppVeyor
2
AsciiDoc
3
ASP.NET Core
55
Atom
4
AWS
2
AWS Cloud9
4
blockdiag
1
Blogger
10
Bootstrap
3
C/C++
6
C#
106
CentOS
3
Chrome
1
Chronograf
3
Codecov
1
CSS
1
Docker
28
DokuWiki
4
Doxygen
1
draw.io
1
Electron.NET
2
Entity Framework Core
9
Excel
2
FFmpeg
2
Firefox
5
Git
12
GitBook
4
GitBucket
7
GitHub
7
GitLab
30
Go
1
Google
1
Google Cloud Platform
1
Grafana
5
HTML
5
IIS
8
InfluxDB
6
JavaScript
7
Jenkins
7
Linux
25
Log4View
1
MahApps.Metro
3
MaterialDesignInXamlToolkit
1
MVC
1
MVVM
6
NLog
3
Node.js
3
npm
1
OpenSSL
3
ownCloud
2
Pine Script
1
PlantUML
5
PowerShell
7
Prism
2
Python
11
Razor
3
Redmine
30
remark.js
2
rocketchat
4
Ruby
3
SignalR
1
Socket.IO
1
SonarQube
5
Sphinx
10
SQL Server
5
SQLite
1
t
1
TestLink
2
Tomcat
2
TortoiseGit
10
TortoiseSVN
2
Trading View
1
Travis CI
1
Ubuntu
13
Visual Studio
39
Visual Studio Code
9
Vue.js
8
Windows
56
Windows 10
4
Windows ADK
1
Windows API
2
Windows Embedded
4
wkhtmltopdf
2
Word
3
WPF
12
WSL
1
Xamarin
1
xUnit
5
アプリケーション
1
デザインパターン
1
テスト
3
バッチファイル
2
ぴよ
3
プログラミング
3
ライセンス
1
ラベル
3
ラベル1
2
英語
2
雑記
1
書籍
1
数学
1
正規表現
1
Blog Archive
▼
2022
(1)
▼
2月
(1)
例えばボタンをクリックしたときに重い処理を実行する場合など、そのまま処理すると GUI が固まって...
►
2021
(24)
►
5月
(7)
►
4月
(8)
►
3月
(2)
►
2月
(2)
►
1月
(5)
►
2020
(60)
►
12月
(1)
►
11月
(3)
►
10月
(3)
►
9月
(3)
►
8月
(3)
►
7月
(7)
►
6月
(7)
►
5月
(2)
►
4月
(6)
►
3月
(6)
►
2月
(7)
►
1月
(12)
►
2019
(92)
►
12月
(13)
►
11月
(9)
►
10月
(3)
►
9月
(2)
►
8月
(3)
►
7月
(5)
►
6月
(11)
►
5月
(6)
►
4月
(17)
►
3月
(9)
►
2月
(6)
►
1月
(8)
►
2018
(100)
►
12月
(1)
►
11月
(11)
►
10月
(8)
►
9月
(6)
►
8月
(10)
►
7月
(10)
►
6月
(8)
►
5月
(9)
►
4月
(8)
►
3月
(14)
►
2月
(4)
►
1月
(11)
►
2017
(117)
►
12月
(14)
►
11月
(20)
►
10月
(17)
►
9月
(19)
►
8月
(10)
►
7月
(8)
►
6月
(3)
►
5月
(6)
►
4月
(5)
►
3月
(2)
►
2月
(8)
►
1月
(5)
►
2016
(91)
►
12月
(5)
►
11月
(9)
►
10月
(11)
►
9月
(9)
►
8月
(6)
►
7月
(14)
►
6月
(14)
►
5月
(11)
►
4月
(10)
►
3月
(2)
►
2015
(23)
►
12月
(4)
►
11月
(2)
►
10月
(8)
►
9月
(8)
►
7月
(1)
►
2013
(3)
►
11月
(1)
►
9月
(1)
►
7月
(1)
►
2012
(2)
►
7月
(1)
►
6月
(1)
►
2011
(1)
►
9月
(1)
►
2009
(1)
►
7月
(1)
►
2008
(2)
►
11月
(1)
►
7月
(1)
►
2007
(3)
►
10月
(3)