CSharp/DictionaryEx.md
... ...
@@ -0,0 +1,749 @@
1
+# DictionaryEx
2
+[[_TOC_]]
3
+
4
+## 概要
5
+- IDictionary<string, string> インターフェースを持ったオブジェクトを JSON 形式でシリアライズ/デシリアライズを行う。
6
+- .NET Framework 3.5 未満の環境で、[JavaScriptSerializer](http://msdn.microsoft.com/ja-jp/library/system.web.script.serialization.javascriptserializer.aspx) が使用できない場合での代替用。
7
+- .NET Framework 2.0 対応。
8
+- キー/値は共に string のみ。
9
+- null はキーとして指定不可。
10
+- 空文字列はキーとして指定可能。(JavaScriptSerializer 非互換)
11
+- ダブルクォーテーション、シングルクォーテーションを含む場合はエスケープする必要がある。
12
+- シリアライズ時のエンコーディングは UTF-16。
13
+
14
+## ソース
15
+- [TakeAsh.DictionaryEx.zip](TakeAsh.DictionaryEx.zip)
16
+
17
+### JSONSerializer.cs
18
+```csharp
19
+/**
20
+ * @mainpage
21
+ * Dictionary を JSON 形式でシリアライズ/デシリアライズする。
22
+ *
23
+ * .NET Framework 3.5 未満の環境で、JavaScriptSerializer が使用できない場合での代替用。<br>
24
+ * .NET Framework 2.0 対応。<br>
25
+ * http://msdn.microsoft.com/ja-jp/library/system.web.script.serialization.javascriptserializer.aspx
26
+ */
27
+
28
+using System;
29
+using System.Collections.Generic;
30
+using System.Text;
31
+using System.Text.RegularExpressions;
32
+
33
+namespace TakeAsh.DictionaryEx
34
+{
35
+ /// <summary>
36
+ /// IDictionary<string, string> インターフェースを持ったオブジェクトを JSON 形式でシリアライズ/デシリアライズを行う。
37
+ /// </summary>
38
+ /// <remarks>
39
+ /// <list type="bullet">
40
+ /// <item>キー/値は共に string のみ。</item>
41
+ /// <item>null はキーとして指定不可。</item>
42
+ /// <item>空文字列はキーとして指定可能。(JavaScriptSerializer 非互換)</item>
43
+ /// <item>ダブルクォーテーション、シングルクォーテーションを含む場合はエスケープする必要がある。</item>
44
+ /// <item>シリアライズ時のエンコーディングは UTF-16。</item>
45
+ /// </list>
46
+ /// </remarks>
47
+ public class JSONSerializer
48
+ {
49
+ /// <summary>
50
+ /// シリアライズの際に削除する末尾の文字。
51
+ /// </summary>
52
+ private static char[] delChar = { ',', ' ', '\t', '\n', '\r', '\f', '\v' };
53
+
54
+ /// <summary>
55
+ /// オブジェクトを JSON 文字列へシリアライズする。
56
+ /// </summary>
57
+ /// <typeparam name="TInput">オブジェクトの型</typeparam>
58
+ /// <param name="dic">キー/値ペアが格納されているオブジェクト</param>
59
+ /// <returns>JSON文字列</returns>
60
+ static public string serialize<TInput>(TInput dic) where TInput : IDictionary<string, string>
61
+ {
62
+ string json = "";
63
+
64
+ if (dic != null)
65
+ {
66
+ foreach (string key in dic.Keys)
67
+ {
68
+ json += "\"" + _Util.encode(key) + "\": \"" + _Util.encode(dic[key]) + "\",\n";
69
+ }
70
+ }
71
+ return "{\n" + json.TrimEnd(delChar) + "\n}\n";
72
+ }
73
+
74
+ /// <summary>
75
+ /// オブジェクトを JSON 文字列へシリアライズする。
76
+ /// </summary>
77
+ /// <typeparam name="TInput">オブジェクトの型</typeparam>
78
+ /// <param name="dic">キー/値ペアが格納されているオブジェクト</param>
79
+ /// <returns>JSON文字列</returns>
80
+ public string Serialize<TInput>(TInput dic) where TInput : IDictionary<string, string>
81
+ {
82
+ return JSONSerializer.serialize(dic);
83
+ }
84
+
85
+ /// <summary>
86
+ /// JSON文字列をデシリアライズし TOutput 型のオブジェクトとして返す。
87
+ /// </summary>
88
+ /// <typeparam name="TOutput">オブジェクトの型</typeparam>
89
+ /// <param name="json">JSON文字列</param>
90
+ /// <returns>TOutput 型のオブジェクト</returns>
91
+ static public TOutput deserialize<TOutput>(string json) where TOutput : IDictionary<string, string>, new()
92
+ {
93
+ TOutput dic = new TOutput();
94
+ Regex reg = new Regex(@"(?<q1>['""])(?<key>[^'""]*)\k<q1>:\s*(?<q2>['""])(?<value>[^'""]*)\k<q2>");
95
+ MatchCollection mc = reg.Matches(_Util.subescape(json));
96
+ foreach (Match m in mc)
97
+ {
98
+ dic[Regex.Unescape(m.Groups["key"].Value)] = Regex.Unescape(m.Groups["value"].Value);
99
+ }
100
+ return dic;
101
+ }
102
+
103
+ /// <summary>
104
+ /// JSON文字列をデシリアライズし TOutput 型のオブジェクトとして返す。
105
+ /// </summary>
106
+ /// <typeparam name="TOutput">オブジェクトの型</typeparam>
107
+ /// <param name="json">JSON文字列</param>
108
+ /// <returns>TOutput 型のオブジェクト</returns>
109
+ public TOutput Deserialize<TOutput>(string json) where TOutput : IDictionary<string, string>, new()
110
+ {
111
+ return deserialize<TOutput>(json);
112
+ }
113
+
114
+ /// <summary>
115
+ /// キー/値ペアを追加する。
116
+ /// </summary>
117
+ /// <remarks>
118
+ /// 既存のキーと衝突する場合は上書きされる。
119
+ /// </remarks>
120
+ /// <typeparam name="TOutput">追加されるオブジェクトの型</typeparam>
121
+ /// <typeparam name="TInput">追加するオブジェクトの型</typeparam>
122
+ /// <param name="dicA">追加されるオブジェクト</param>
123
+ /// <param name="dicB">追加するオブジェクト</param>
124
+ /// <returns>追加されたオブジェクト</returns>
125
+ static public TOutput push<TOutput, TInput>(ref TOutput dicA, TInput dicB)
126
+ where TOutput : IDictionary<string, string>, new()
127
+ where TInput : IDictionary<string, string>
128
+ {
129
+ if (dicA == null)
130
+ {
131
+ dicA = new TOutput();
132
+ }
133
+ if (dicB != null)
134
+ {
135
+ foreach (string key in dicB.Keys)
136
+ {
137
+ dicA[key] = dicB[key];
138
+ }
139
+ }
140
+ return dicA;
141
+ }
142
+
143
+ /// <summary>
144
+ /// オブジェクトに格納されたキー/値ペアを追加する。
145
+ /// </summary>
146
+ /// <remarks>
147
+ /// 既存のキーと衝突する場合は上書きされる。
148
+ /// </remarks>
149
+ /// <typeparam name="TOutput">追加されるオブジェクトの型</typeparam>
150
+ /// <typeparam name="TInput">追加するオブジェクトの型</typeparam>
151
+ /// <param name="dicA">追加されるオブジェクト</param>
152
+ /// <param name="dicB">追加するオブジェクト</param>
153
+ /// <returns>追加されたオブジェクト</returns>
154
+ public TOutput Push<TOutput, TInput>(ref TOutput dicA, TInput dicB)
155
+ where TOutput : IDictionary<string, string>, new()
156
+ where TInput : IDictionary<string, string>
157
+ {
158
+ return push(ref dicA, dicB);
159
+ }
160
+
161
+ /// <summary>
162
+ /// JSON 文字列を解釈しキー/値ペアを追加する。
163
+ /// </summary>
164
+ /// <remarks>
165
+ /// 既存のキーと衝突する場合は上書きされる。
166
+ /// </remarks>
167
+ /// <typeparam name="TOutput">追加されるオブジェクトの型</typeparam>
168
+ /// <param name="dic">追加されるオブジェクト</param>
169
+ /// <param name="json">追加する JSON 文字列</param>
170
+ /// <returns>追加されたオブジェクト</returns>
171
+ static public TOutput push<TOutput>(ref TOutput dic, string json) where TOutput : IDictionary<string, string>, new()
172
+ {
173
+ return push(ref dic, deserialize<TOutput>(json));
174
+ }
175
+
176
+ /// <summary>
177
+ /// JSON 文字列を解釈しキー/値ペアを追加する。
178
+ /// </summary>
179
+ /// <remarks>
180
+ /// 既存のキーと衝突する場合は上書きされる。
181
+ /// </remarks>
182
+ /// <typeparam name="TOutput">追加されるオブジェクトの型</typeparam>
183
+ /// <param name="dic">追加されるオブジェクト</param>
184
+ /// <param name="json">追加する JSON 文字列</param>
185
+ /// <returns>追加されたオブジェクト</returns>
186
+ public TOutput Push<TOutput>(ref TOutput dic, string json) where TOutput : IDictionary<string, string>, new()
187
+ {
188
+ return push(ref dic, deserialize<TOutput>(json));
189
+ }
190
+ }
191
+}
192
+
193
+// EOF
194
+```
195
+
196
+### _Util.cs
197
+```csharp
198
+using System;
199
+using System.Text;
200
+using System.Text.RegularExpressions;
201
+
202
+namespace TakeAsh.DictionaryEx
203
+{
204
+ internal class _Util
205
+ {
206
+ /// <summary>
207
+ /// Shift_JIS 範囲に対応する文字クラス
208
+ /// </summary>
209
+ /// <remarks>
210
+ /// この範囲にマッチする文字はエスケープしない。
211
+ /// </remarks>
212
+ private static Regex regKanji = new Regex(
213
+ @"["
214
+ //+ @"\p{IsBasicLatin}" // 制御文字を含むのでマッチ範囲から外す
215
+ + @"\p{IsLatin-1Supplement}"
216
+ + @"\p{IsGreek}"
217
+ + @"\p{IsCyrillic}"
218
+ + @"\p{IsGeneralPunctuation}"
219
+ + @"\p{IsLetterlikeSymbols}"
220
+ + @"\p{IsNumberForms}"
221
+ + @"\p{IsArrows}"
222
+ + @"\p{IsMathematicalOperators}"
223
+ + @"\p{IsMiscellaneousTechnical}"
224
+ + @"\p{IsEnclosedAlphanumerics}"
225
+ + @"\p{IsBoxDrawing}"
226
+ + @"\p{IsGeometricShapes}"
227
+ + @"\p{IsMiscellaneousSymbols}"
228
+ + @"\p{IsCJKSymbolsandPunctuation}"
229
+ + @"\p{IsHiragana}"
230
+ + @"\p{IsKatakana}"
231
+ + @"\p{IsEnclosedCJKLettersandMonths}"
232
+ + @"\p{IsCJKCompatibility}"
233
+ + @"\p{IsCJKUnifiedIdeographs}"
234
+ + @"\p{IsCJKCompatibilityIdeographs}"
235
+ + @"\p{IsHalfwidthandFullwidthForms}"
236
+ + @"]"
237
+ );
238
+
239
+ /// <summary>
240
+ /// 引用符のエスケープ形式を変換する。
241
+ /// </summary>
242
+ /// <remarks>
243
+ /// <list type="bullet">
244
+ /// <item>\\" → \\u0022</item>
245
+ /// <item>\\' → \\u0027</item>
246
+ /// </list>
247
+ /// </remarks>
248
+ /// <param name="str">文字列</param>
249
+ /// <returns>エスケープされた文字列</returns>
250
+ public static string subescape(string str)
251
+ {
252
+ Regex regQuote = new Regex(@"\\(?<char>[""'])");
253
+ return regQuote.Replace(str, new MatchEvaluator(toHex));
254
+ }
255
+
256
+ /// <summary>
257
+ /// 記号等の文字をエスケープする。
258
+ /// </summary>
259
+ /// <remarks>
260
+ /// 文字クラス http://msdn.microsoft.com/ja-jp/library/20bw873z
261
+ /// </remarks>
262
+ /// <param name="str">文字列</param>
263
+ /// <returns>エスケープされた文字列</returns>
264
+ public static string encode(string str)
265
+ {
266
+ Regex regEscape = new Regex(
267
+ @"(?<char>[^-0-9A-Za-z\s\[\]\{\}"
268
+ + Regex.Escape("!#$%&()*+,./:;=?@^_`|~")
269
+ + @"])"
270
+ );
271
+ return regEscape.Replace(str, new MatchEvaluator(toHex));
272
+ }
273
+
274
+ /// <summary>
275
+ /// 文字を16進化する。
276
+ /// </summary>
277
+ /// <remarks>
278
+ ///
279
+ /// </remarks>
280
+ /// <param name="m">文字(グループ名"char")</param>
281
+ /// <returns>16進化した文字</returns>
282
+ public static string toHex(Match m)
283
+ {
284
+ string c1 = m.Groups["char"].Value;
285
+ int code = (int)c1[0];
286
+ bool f1 = !regKanji.Match(c1).Success;
287
+ bool f2 = !IsShiftJIS(c1);
288
+ string ret = (f1 || f2) ? String.Format(@"\u{0:x4}", code) : c1;
289
+ return ret;
290
+ }
291
+
292
+ /// <summary>
293
+ /// Shift_JIS 範囲内の文字のみかどうかをチェックして、その結果を返す。
294
+ /// </summary>
295
+ /// <remarks>
296
+ /// http://acha-ya.cocolog-nifty.com/blog/2010/12/unicode-ef79.html
297
+ /// </remarks>
298
+ /// <param name="checkString">チェック対象の文字列</param>
299
+ /// <returns>
300
+ /// <list type="bullet">
301
+ /// <item>true: 全ての文字は Shift_JIS 範囲内である</item>
302
+ /// <item>false: Shift_JIS 範囲外の文字が含まれている</item>
303
+ /// </list>
304
+ /// </returns>
305
+ public static bool IsShiftJIS(string checkString)
306
+ {
307
+ byte[] translateBuffer = Encoding.GetEncoding("shift_jis").GetBytes(checkString);
308
+ string translateString = Encoding.GetEncoding("shift_jis").GetString(translateBuffer);
309
+ return (checkString == translateString.ToString());
310
+ }
311
+ }
312
+}
313
+
314
+// EOF
315
+```
316
+
317
+### JSONableDictionary.cs
318
+```csharp
319
+using System;
320
+using System.Collections;
321
+using System.Collections.Generic;
322
+using System.Text.RegularExpressions;
323
+
324
+namespace TakeAsh.DictionaryEx
325
+{
326
+ /// <summary>
327
+ /// JSON 形式としてシリアライズ/デシリアライズできる Dictionary
328
+ /// </summary>
329
+ /// <remarks>
330
+ /// <list type="bullet">
331
+ /// <item>シリアライズに際して、キーの順番はソートされない。</item>
332
+ /// <item>キー/値は共に string のみ。</item>
333
+ /// <item>null はキーとして指定不可。</item>
334
+ /// <item>空文字列はキーとして指定可能。(JavaScriptSerializer 非互換)</item>
335
+ /// <item>ダブルクォーテーション、シングルクォーテーションを含む場合はエスケープする必要がある。</item>
336
+ /// <item>シリアライズ時のエンコーディングは UTF-16。</item>
337
+ /// </list>
338
+ /// </remarks>
339
+ public class JSONableDictionary : Dictionary<string,string>
340
+ {
341
+ /// <summary>
342
+ /// コンストラクタ
343
+ /// </summary>
344
+ public JSONableDictionary()
345
+ : base()
346
+ {
347
+ }
348
+
349
+ /// <summary>
350
+ /// コンストラクタ
351
+ /// </summary>
352
+ /// <param name="dic">キー/値ペア</param>
353
+ public JSONableDictionary(IDictionary<string, string> dic)
354
+ : base(dic)
355
+ {
356
+ foreach (string key in dic.Keys)
357
+ {
358
+ this[key] = dic[key];
359
+ }
360
+ }
361
+
362
+ /// <summary>
363
+ /// コンストラクタ
364
+ /// </summary>
365
+ /// <param name="json">JSON文字列</param>
366
+ public JSONableDictionary(string json)
367
+ {
368
+ Dictionary<string, string> dic = JSONSerializer.deserialize<Dictionary<string, string>>(json);
369
+ foreach (string key in dic.Keys)
370
+ {
371
+ this[key] = dic[key];
372
+ }
373
+ }
374
+
375
+ /// <summary>
376
+ /// JSON文字列をデシリアライズし自身にセットする。
377
+ /// </summary>
378
+ /// <remarks>
379
+ /// 既存の要素は消去される。
380
+ /// </remarks>
381
+ /// <param name="json">JSON文字列</param>
382
+ /// <returns>this</returns>
383
+ public JSONableDictionary Deserialize(string json)
384
+ {
385
+ this.Clear();
386
+ Dictionary<string, string> dic = JSONSerializer.deserialize<Dictionary<string, string>>(json);
387
+ foreach (string key in dic.Keys)
388
+ {
389
+ this[key] = dic[key];
390
+ }
391
+ return this;
392
+ }
393
+
394
+ /// <summary>
395
+ /// JSON文字列としてシリアライズする。
396
+ /// </summary>
397
+ /// <returns>JSON文字列</returns>
398
+ public string Serialize()
399
+ {
400
+ return JSONSerializer.serialize(this);
401
+ }
402
+
403
+ /// <summary>
404
+ /// キー/値ペアを追加する。
405
+ /// </summary>
406
+ /// <remarks>
407
+ /// 既存のキーと重複する場合は上書きされる。
408
+ /// </remarks>
409
+ /// <param name="dic">追加するキー/値ペア</param>
410
+ /// <returns>this</returns>
411
+ public JSONableDictionary Push<T>(T dic) where T : IDictionary<string, string>
412
+ {
413
+ foreach (string key in dic.Keys)
414
+ {
415
+ this[key] = dic[key];
416
+ }
417
+ return this;
418
+ }
419
+
420
+ /// <summary>
421
+ /// json文字列をデシリアライズし追加する。
422
+ /// </summary>
423
+ /// <param name="json">JSON文字列</param>
424
+ /// <returns>this</returns>
425
+ public JSONableDictionary Push(string json)
426
+ {
427
+ JSONableDictionary dic = Deserialize(json);
428
+ Push(dic);
429
+ return this;
430
+ }
431
+
432
+ /// <summary>
433
+ /// 現在のオブジェクトを表す文字列を返す。
434
+ /// </summary>
435
+ /// <returns>現在のオブジェクトを表す文字列</returns>
436
+ public new string ToString()
437
+ {
438
+ return Serialize();
439
+ }
440
+
441
+ /// <summary>
442
+ /// オブジェクト同士を比較する。
443
+ /// </summary>
444
+ /// <param name="other">比較対象オブジェクト</param>
445
+ /// <returns>
446
+ /// <list type="bullet">
447
+ /// <item>true: 値が一致</item>
448
+ /// <item>false:
449
+ /// <list type="bullet">
450
+ /// <item>比較対象オブジェクトが null</item>
451
+ /// <item>比較対象オブジェクトの型が異なる</item>
452
+ /// <item>値が不一致</item>
453
+ /// </list>
454
+ /// </item>
455
+ /// </list>
456
+ /// </returns>
457
+ public override bool Equals(object other)
458
+ {
459
+ if (other == null)
460
+ {
461
+ return false;
462
+ }
463
+ JSONableDictionary p = other as JSONableDictionary;
464
+ if ((Object)p == null)
465
+ {
466
+ return false;
467
+ }
468
+ return this.Serialize() == p.Serialize();
469
+ }
470
+
471
+ /// <summary>
472
+ /// ハッシュ コードを返す。
473
+ /// </summary>
474
+ /// <returns>現在のハッシュ コード</returns>
475
+ public override int GetHashCode()
476
+ {
477
+ return base.GetHashCode();
478
+ }
479
+ }
480
+}
481
+
482
+// EOF
483
+```
484
+
485
+### JSONableSortedDictionary.cs
486
+```csharp
487
+using System;
488
+using System.Collections;
489
+using System.Collections.Generic;
490
+using System.Text.RegularExpressions;
491
+
492
+namespace TakeAsh.DictionaryEx
493
+{
494
+ /// <summary>
495
+ /// JSON 形式としてシリアライズ/デシリアライズできる SortedDictionary
496
+ /// </summary>
497
+ /// <remarks>
498
+ /// <list type="bullet">
499
+ /// <item>シリアライズに際して、キーの順番でソートされる。</item>
500
+ /// <item>キー/値は共に string のみ。</item>
501
+ /// <item>null はキーとして指定不可。</item>
502
+ /// <item>空文字列はキーとして指定可能。(JavaScriptSerializer 非互換)</item>
503
+ /// <item>ダブルクォーテーション、シングルクォーテーションを含む場合はエスケープする必要がある。</item>
504
+ /// <item>シリアライズ時のエンコーディングは UTF-16。</item>
505
+ /// </list>
506
+ /// </remarks>
507
+ public class JSONableSortedDictionary : SortedDictionary<string, string>
508
+ {
509
+ /// <summary>
510
+ /// コンストラクタ
511
+ /// </summary>
512
+ public JSONableSortedDictionary()
513
+ : base()
514
+ {
515
+ }
516
+
517
+ /// <summary>
518
+ /// コンストラクタ
519
+ /// </summary>
520
+ /// <param name="dic">キー/値ペア</param>
521
+ public JSONableSortedDictionary(IDictionary<string, string> dic)
522
+ : base(dic)
523
+ {
524
+ foreach (string key in dic.Keys)
525
+ {
526
+ this[key] = dic[key];
527
+ }
528
+ }
529
+
530
+ /// <summary>
531
+ /// コンストラクタ
532
+ /// </summary>
533
+ /// <param name="json">JSON文字列</param>
534
+ public JSONableSortedDictionary(string json)
535
+ {
536
+ Dictionary<string, string> dic = JSONSerializer.deserialize<Dictionary<string, string>>(json);
537
+ foreach (string key in dic.Keys)
538
+ {
539
+ this[key] = dic[key];
540
+ }
541
+ }
542
+
543
+ /// <summary>
544
+ /// JSON文字列をデシリアライズし自身にセットする。
545
+ /// </summary>
546
+ /// <remarks>
547
+ /// 既存の要素は消去される。
548
+ /// </remarks>
549
+ /// <param name="json">JSON文字列</param>
550
+ /// <returns>this</returns>
551
+ public JSONableSortedDictionary Deserialize(string json)
552
+ {
553
+ this.Clear();
554
+ Dictionary<string, string> dic = JSONSerializer.deserialize<Dictionary<string, string>>(json);
555
+ foreach (string key in dic.Keys)
556
+ {
557
+ this[key] = dic[key];
558
+ }
559
+ return this;
560
+ }
561
+
562
+ /// <summary>
563
+ /// JSON文字列としてシリアライズする。
564
+ /// </summary>
565
+ /// <returns>JSON文字列</returns>
566
+ public string Serialize()
567
+ {
568
+ return JSONSerializer.serialize(this);
569
+ }
570
+
571
+ /// <summary>
572
+ /// キー/値ペアを追加する。
573
+ /// </summary>
574
+ /// <remarks>
575
+ /// 既存のキーと重複する場合は上書きされる。
576
+ /// </remarks>
577
+ /// <param name="dic">追加するキー/値ペア</param>
578
+ /// <returns>this</returns>
579
+ public JSONableSortedDictionary Push<T>(T dic) where T : IDictionary<string, string>
580
+ {
581
+ foreach (string key in dic.Keys)
582
+ {
583
+ this[key] = dic[key];
584
+ }
585
+ return this;
586
+ }
587
+
588
+ /// <summary>
589
+ /// json文字列をデシリアライズし追加する。
590
+ /// </summary>
591
+ /// <param name="json">JSON文字列</param>
592
+ /// <returns>this</returns>
593
+ public JSONableSortedDictionary Push(string json)
594
+ {
595
+ JSONableSortedDictionary dic = Deserialize(json);
596
+ Push(dic);
597
+ return this;
598
+ }
599
+
600
+ /// <summary>
601
+ /// 現在のオブジェクトを表す文字列を返す。
602
+ /// </summary>
603
+ /// <returns>現在のオブジェクトを表す文字列</returns>
604
+ public new string ToString()
605
+ {
606
+ return Serialize();
607
+ }
608
+
609
+ /// <summary>
610
+ /// オブジェクト同士を比較する。
611
+ /// </summary>
612
+ /// <param name="other">比較対象オブジェクト</param>
613
+ /// <returns>
614
+ /// <list type="bullet">
615
+ /// <item>true: 値が一致</item>
616
+ /// <item>false:
617
+ /// <list type="bullet">
618
+ /// <item>比較対象オブジェクトが null</item>
619
+ /// <item>比較対象オブジェクトの型が異なる</item>
620
+ /// <item>値が不一致</item>
621
+ /// </list>
622
+ /// </item>
623
+ /// </list>
624
+ /// </returns>
625
+ public override bool Equals(object other)
626
+ {
627
+ if (other == null)
628
+ {
629
+ return false;
630
+ }
631
+ JSONableSortedDictionary p = other as JSONableSortedDictionary;
632
+ if ((Object)p == null)
633
+ {
634
+ return false;
635
+ }
636
+ return this.Serialize() == p.Serialize();
637
+ }
638
+
639
+ /// <summary>
640
+ /// ハッシュ コードを返す。
641
+ /// </summary>
642
+ /// <returns>現在のハッシュ コード</returns>
643
+ public override int GetHashCode()
644
+ {
645
+ return base.GetHashCode();
646
+ }
647
+ }
648
+}
649
+
650
+// EOF
651
+```
652
+
653
+### Program.cs
654
+```csharp
655
+using System;
656
+using System.Collections;
657
+using System.Collections.Generic;
658
+using System.Text.RegularExpressions;
659
+using System.Web.Script.Serialization;
660
+using TakeAsh.DictionaryEx;
661
+
662
+namespace Tester
663
+{
664
+ class Program
665
+ {
666
+ static void Main(string[] args)
667
+ {
668
+ JavaScriptSerializer jss = new JavaScriptSerializer();
669
+ JSONSerializer tjs = new JSONSerializer();
670
+ Dictionary<string, string> dic1 = new Dictionary<string, string>();
671
+ dic1["A"] = "AAA";
672
+ dic1["a"] = "aaa";
673
+ dic1["123"] = "abc";
674
+ dic1["あ"] = "あ";
675
+ dic1[""] = "BlankKey";
676
+ dic1["Escape"] = "\\\"\'\t\n\\\"\'\t\n";
677
+ dic1["Unicode"] = "\u9AD8\u9ad9 \u5D0E\ufa11 \u5409\uD842\uDFB7 \u53F1\uD842\uDF9F \u5265\u525D \u586B\u5861 \u982C\u9830";
678
+ dic1["Latin-1Supplement"] = "€§¨°±´¶×÷";
679
+ dic1["Greek"] = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω";
680
+ dic1["Cyrillic"] = "ЁАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
681
+ +"абвгдежзийклмнопрстуфхцчшщъыьэюяё";
682
+ dic1["GeneralPunctuation"] = "‐―‘’“”†‡‥…‰′″※";
683
+ dic1["LetterlikeSymbols"] = "℃№℡Å";
684
+ dic1["NumberForms"] = "ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹ";
685
+ dic1["Arrows"] = "←↑→↓⇒⇔";
686
+ dic1["MathematicalOperators"] = "∀∂∃∇∈∋∑√∝∞∟∠∥∧∨∩∪∫∬∮∴∵∽≒≠≡≦≧≪≫⊂⊃⊆⊇⊥⊿";
687
+ dic1["MiscellaneousTechnical"] = "⌒";
688
+ dic1["EnclosedAlphanumerics"] = "①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳";
689
+ dic1["BoxDrawing"] = "─━│┃┌┏┐┓└┗┘┛├┝┠┣┤┥┨┫┬┯┰┳┴┷┸┻┼┿╂╋";
690
+ dic1["GeometricShapes"] = "■□▲△▼▽◆◇○◎●◯";
691
+ dic1["MiscellaneousSymbols"] = "★☆♀♂♪♭♯";
692
+ dic1["CJKSymbolsandPunctuation"] = " 、。〃々〆〇〈〉《》「」『』【】〒〓〔〕〝〟";
693
+ dic1["Hiragana"] = "あかさたなはまやらわをん";
694
+ dic1["Katakana"] = "アカサタナハマヤラワヲン";
695
+ dic1["EnclosedCJKLettersandMonths"] = "㈱㈲㈹㊤㊥㊦㊧㊨";
696
+ dic1["CJKCompatibility"] = "㌃㌍㌔㌘㌢㌣㌦㌧㌫㌶㌻㍉㍊㍍㍑㍗㍻㍼㍽㍾㎎㎏㎜㎝㎞㎡㏄㏍";
697
+ dic1["CJKUnifiedIdeographs"] = "一丁七万丈三上下不与丐丑且丕世丗丘丙丞両";
698
+ dic1["CJKCompatibilityIdeographs"] = "朗隆﨎﨏塚﨑晴﨓﨔凞猪益礼神祥福靖精羽﨟蘒﨡諸﨣﨤逸都﨧﨨﨩飯飼館鶴";
699
+ dic1["HalfwidthandFullwidthForms"] = "!"#$%&'()*+,-./0123456789:;<=>?"
700
+ + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"
701
+ + "`abcdefghijklmnopqrstuvwxyz{|}~。"
702
+ + "「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚¢£¬ ̄¦¥";
703
+ for (int high = 0; high < 8; ++high)
704
+ {
705
+ string buf = "";
706
+ for (int low = 0; low < 16; ++low)
707
+ {
708
+ buf += ((char)(high * 16 + low)).ToString();
709
+ }
710
+ dic1[String.Format("{0:x2}", high)] = buf;
711
+ }
712
+ string tjsJSON = tjs.Serialize(dic1);
713
+ Console.WriteLine("TakeAsh/JSONSerializer dic1\n{0}", tjsJSON);
714
+ string jssJSON = jss.Serialize(dic1) + "\n";
715
+ Console.WriteLine("System/JavaScriptSerializer dic1\n{0}", jssJSON);
716
+
717
+ JSONableSortedDictionary dic2 = new JSONableSortedDictionary();
718
+ dic2.Deserialize(jssJSON);
719
+ Console.WriteLine("Syste/Serialize -> TakeAsh/Deserialize(SortedDictionary))\n{0}", tjs.Serialize(dic2));
720
+ SortedDictionary<string, string> dic3 = null;
721
+ try
722
+ {
723
+ dic3 = jss.Deserialize<SortedDictionary<string, string>>(tjsJSON);
724
+ }
725
+ catch (Exception e)
726
+ {
727
+ Console.WriteLine("Exception: {0}\n", e);
728
+ }
729
+ tjsJSON = Regex.Replace(tjsJSON, "\"\":\\s*\"[^\"]*\",", ""); // 空文字列なキーを削除
730
+ dic3 = jss.Deserialize<SortedDictionary<string, string>>(tjsJSON);
731
+ Console.WriteLine("TakeAsh/Serialize -> Syste/Deserialize(SortedDictionary))\n{0}", tjs.Serialize(dic3));
732
+ Console.WriteLine("eq? (空文字列キーなし): {0}", dic2.Equals(new JSONableSortedDictionary(dic3)));
733
+ dic3[""] = "BlankKey";
734
+ Console.WriteLine("eq? (空文字列キー追加): {0}", dic2.Equals(new JSONableSortedDictionary(dic3)));
735
+ }
736
+ }
737
+}
738
+
739
+//EOF
740
+```
741
+
742
+## リンク
743
+- [[Listup Shift_JIS Class|/CSharp/ListupShiftJISClass]]
744
+
745
+- [JavaScriptSerializer クラス (System.Web.Script.Serialization)](http://msdn.microsoft.com/ja-jp/library/system.web.script.serialization.javascriptserializer.aspx)
746
+- [IDictionary(TKey, TValue) インターフェイス (System.Collections.Generic)](http://msdn.microsoft.com/ja-jp/library/s4ys34ea)
747
+- [文字クラス](http://msdn.microsoft.com/ja-jp/library/20bw873z)
748
+
749
+- [文字列にUnicode固有文字が含まれるかのチェック方法: C#研究所](http://acha-ya.cocolog-nifty.com/blog/2010/12/unicode-ef79.html)
... ...
\ No newline at end of file
CSharp/Home.md
... ...
@@ -0,0 +1,44 @@
1
+[[_TOC_]]
2
+
3
+# サンプルスクリプト
4
+- [[DictionaryEx]]
5
+- [[ListupShiftJISClass]]
6
+- [[NuGet]]
7
+- [[NUnit|/CSharp/NUnit/Home]]
8
+ - [[NUnit-VS-TagJump|/CSharp/NUnit/NUnit-VS-TagJump]]
9
+- [[scanNetArp]]
10
+
11
+- [GitHub:TakeAsh/cs-SerializableDictionary](https://github.com/TakeAsh/cs-SerializableDictionary)<br />
12
+XMLシリアライズ可能な Dictionary クラス, ListableDictionary
13
+
14
+- [GitHub:TakeAsh/cs-EnumHelper](https://github.com/TakeAsh/cs-EnumHelper)<br />
15
+リソースまたは Description 属性が付いた enum のヘルパークラス<br />
16
+コンボボックス割当を簡素化<br />
17
+ExtraProperties 属性(enum に Dictionary&lt;string, string&gt; を割当)
18
+
19
+- [GitHub:TakeAsh/cs-SmtpClient](https://github.com/TakeAsh/cs-SmtpClient)<br />
20
+Simple SMTP Client<br />
21
+![https://raw.githubusercontent.com/TakeAsh/cs-SmtpClient/master/Util/SS.png](https://raw.githubusercontent.com/TakeAsh/cs-SmtpClient/master/Util/SS.png)
22
+
23
+- [GitHub:TakeAsh/cs-TakeAshUtility](https://github.com/TakeAsh/cs-TakeAshUtility)
24
+
25
+- [GitHub:TakeAsh/cs-WpfUtility](https://github.com/TakeAsh/cs-WpfUtility)
26
+ - [MessageButton](https://github.com/TakeAsh/cs-WpfUtility/wiki/MessageButton) is an alternative 'MessageBox' that can be pinned on window as an icon.
27
+ - [PaneledTab](https://github.com/TakeAsh/cs-WpfUtility/wiki/PaneledTab) is TabContorl with 'FormerPanel' and 'LatterPanel' beside TabPanel.
28
+ - [PlaceHolder](https://github.com/TakeAsh/cs-WpfUtility/wiki/PlaceHolder) realize place holder for TextBox and ComboBox in .Net 4.0.
29
+ - [ResourceHelper](https://github.com/TakeAsh/cs-WpfUtility/wiki/ResourceHelper) returns resource from the CallingAssembly.
30
+ - [RibbonExtensionMethods](https://github.com/TakeAsh/cs-WpfUtility/wiki/RibbonExtensionMethods) add helper methods to Ribbon.
31
+ - [SoftBreak](https://github.com/TakeAsh/cs-WpfUtility/wiki/SoftBreak) realize 'Word Break' and 'Soft Hyphen' in Label of RibbonButton.
32
+ - [TrExtension](https://github.com/TakeAsh/cs-WpfUtility/wiki/TrExtension) (Translation Extension) show string resource reflexing language setting.
33
+
34
+- [GitHub:TakeAsh/cs-MkShortCut](https://github.com/TakeAsh/cs-MkShortCut)<br />
35
+The command line tool to make a shortcut.
36
+
37
+# リンク
38
+- [.NET Framework 4.7, 4.6, and 4.5 - Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/articles/framework/)
39
+
40
+- [.NET SDKs and Targeting Packs](http://blogs.msdn.com/b/dotnet/p/dotnet_sdks.aspx)
41
+
42
+- [.NET Framework クラス ライブラリ](http://msdn.microsoft.com/ja-jp/library/gg145045)
43
+
44
+- [C#で始めるテスト駆動開発入門:CodeZine](http://codezine.jp/article/corner/446)
... ...
\ No newline at end of file
CSharp/ListupShiftJISClass.md
... ...
@@ -0,0 +1,227 @@
1
+[[_TOC_]]
2
+
3
+# 概要
4
+- Shift_JIS 範囲内の文字が Unicode のどの文字クラスに当たるのかを調べリストアップする。
5
+
6
+# ソース
7
+- [ListupShiftJISClass.zip](ListupShiftJISClass.zip)
8
+- Program.cs
9
+```csharp
10
+using System;
11
+using System.Collections.Generic;
12
+using System.Linq;
13
+using System.Text;
14
+using System.Text.RegularExpressions;
15
+
16
+namespace ListupShiftJISClass
17
+{
18
+ class Program
19
+ {
20
+ /// <summary>
21
+ /// .NET Framework の文字クラス名
22
+ /// http://msdn.microsoft.com/ja-jp/library/20bw873z
23
+ /// </summary>
24
+ static string[] ClassNames ={
25
+ "BasicLatin",
26
+ "Latin-1Supplement",
27
+ "LatinExtended-A",
28
+ "LatinExtended-B",
29
+ "IPAExtensions",
30
+ "SpacingModifierLetters",
31
+ "CombiningDiacriticalMarks",
32
+ "Greek",
33
+ "GreekandCoptic",
34
+ "Cyrillic",
35
+ "CyrillicSupplement",
36
+ "Armenian",
37
+ "Hebrew",
38
+ "Arabic",
39
+ "Syriac",
40
+ "Thaana",
41
+ "Devanagari",
42
+ "Bengali",
43
+ "Gurmukhi",
44
+ "Gujarati",
45
+ "Oriya",
46
+ "Tamil",
47
+ "Telugu",
48
+ "Kannada",
49
+ "Malayalam",
50
+ "Sinhala",
51
+ "Thai",
52
+ "Lao",
53
+ "Tibetan",
54
+ "Myanmar",
55
+ "Georgian",
56
+ "HangulJamo",
57
+ "Ethiopic",
58
+ "Cherokee",
59
+ "UnifiedCanadianAboriginalSyllabics",
60
+ "Ogham",
61
+ "Runic",
62
+ "Tagalog",
63
+ "Hanunoo",
64
+ "Buhid",
65
+ "Tagbanwa",
66
+ "Khmer",
67
+ "Mongolian",
68
+ "Limbu",
69
+ "TaiLe",
70
+ "KhmerSymbols",
71
+ "PhoneticExtensions",
72
+ "LatinExtendedAdditional",
73
+ "GreekExtended",
74
+ "GeneralPunctuation",
75
+ "SuperscriptsandSubscripts",
76
+ "CurrencySymbols",
77
+ "CombiningDiacriticalMarksforSymbols",
78
+ "CombiningMarksforSymbols",
79
+ "LetterlikeSymbols",
80
+ "NumberForms",
81
+ "Arrows",
82
+ "MathematicalOperators",
83
+ "MiscellaneousTechnical",
84
+ "ControlPictures",
85
+ "OpticalCharacterRecognition",
86
+ "EnclosedAlphanumerics",
87
+ "BoxDrawing",
88
+ "BlockElements",
89
+ "GeometricShapes",
90
+ "MiscellaneousSymbols",
91
+ "Dingbats",
92
+ "MiscellaneousMathematicalSymbols-A",
93
+ "SupplementalArrows-A",
94
+ "BraillePatterns",
95
+ "SupplementalArrows-B",
96
+ "MiscellaneousMathematicalSymbols-B",
97
+ "SupplementalMathematicalOperators",
98
+ "MiscellaneousSymbolsandArrows",
99
+ "CJKRadicalsSupplement",
100
+ "KangxiRadicals",
101
+ "IdeographicDescriptionCharacters",
102
+ "CJKSymbolsandPunctuation",
103
+ "Hiragana",
104
+ "Katakana",
105
+ "Bopomofo",
106
+ "HangulCompatibilityJamo",
107
+ "Kanbun",
108
+ "BopomofoExtended",
109
+ "KatakanaPhoneticExtensions",
110
+ "EnclosedCJKLettersandMonths",
111
+ "CJKCompatibility",
112
+ "CJKUnifiedIdeographsExtensionA",
113
+ "YijingHexagramSymbols",
114
+ "CJKUnifiedIdeographs",
115
+ "YiSyllables",
116
+ "YiRadicals",
117
+ "HangulSyllables",
118
+ "HighSurrogates",
119
+ "HighPrivateUseSurrogates",
120
+ "LowSurrogates",
121
+ "PrivateUse",
122
+ "PrivateUseArea",
123
+ "CJKCompatibilityIdeographs",
124
+ "AlphabeticPresentationForms",
125
+ "ArabicPresentationForms-A",
126
+ "VariationSelectors",
127
+ "CombiningHalfMarks",
128
+ "CJKCompatibilityForms",
129
+ "SmallFormVariants",
130
+ "ArabicPresentationForms-B",
131
+ "HalfwidthandFullwidthForms",
132
+ "Specials",
133
+ };
134
+ static Dictionary<string, Regex> regCharClasses = new Dictionary<string, Regex>();
135
+
136
+ static void Main(string[] args)
137
+ {
138
+ foreach (string classname in ClassNames)
139
+ {
140
+ regCharClasses[classname] = new Regex(@"\p{Is" + classname + "}");
141
+ }
142
+ Dictionary<string, string> result = new Dictionary<string, string>();
143
+ for (int code = 0x00; code <= 0xffff; ++code)
144
+ {
145
+ string c = ((char)code).ToString();
146
+ if (IsShiftJIS(c))
147
+ {
148
+ string classname = getClassName(c);
149
+ result[classname] = (result.ContainsKey(classname)) ? result[classname] + c : c;
150
+ }
151
+ }
152
+ foreach (string classname in result.Keys)
153
+ {
154
+ Console.WriteLine("{0}", classname);
155
+ //Console.WriteLine("{0}\n{1}\n", classname, result[classname]);
156
+ }
157
+ }
158
+
159
+ /// <summary>
160
+ /// Shift_JIS 範囲内の文字のみかどうかをチェックして、その結果を返す。
161
+ /// </summary>
162
+ /// <remarks>
163
+ /// http://acha-ya.cocolog-nifty.com/blog/2010/12/unicode-ef79.html
164
+ /// </remarks>
165
+ /// <param name="checkString">チェック対象の文字列</param>
166
+ /// <returns>
167
+ /// <list type="bullet">
168
+ /// <item>true: 全ての文字は Shift_JIS 範囲内である</item>
169
+ /// <item>false: Shift_JIS 範囲外の文字が含まれている</item>
170
+ /// </list>
171
+ /// </returns>
172
+ static bool IsShiftJIS(string checkString)
173
+ {
174
+ byte[] translateBuffer = Encoding.GetEncoding("shift_jis").GetBytes(checkString);
175
+ string translateString = Encoding.GetEncoding("shift_jis").GetString(translateBuffer);
176
+ return (checkString == translateString.ToString());
177
+ }
178
+
179
+ static string getClassName(string c)
180
+ {
181
+ string result = "-"; // Not found
182
+ foreach (string classname in ClassNames)
183
+ {
184
+ Match m = regCharClasses[classname].Match(c);
185
+ if (m.Success)
186
+ {
187
+ result = classname;
188
+ break;
189
+ }
190
+ }
191
+ return result;
192
+ }
193
+ }
194
+}
195
+```
196
+
197
+# 出力
198
+```
199
+BasicLatin
200
+Latin-1Supplement
201
+Greek
202
+Cyrillic
203
+GeneralPunctuation
204
+LetterlikeSymbols
205
+NumberForms
206
+Arrows
207
+MathematicalOperators
208
+MiscellaneousTechnical
209
+EnclosedAlphanumerics
210
+BoxDrawing
211
+GeometricShapes
212
+MiscellaneousSymbols
213
+CJKSymbolsandPunctuation
214
+Hiragana
215
+Katakana
216
+EnclosedCJKLettersandMonths
217
+CJKCompatibility
218
+CJKUnifiedIdeographs
219
+PrivateUse
220
+CJKCompatibilityIdeographs
221
+HalfwidthandFullwidthForms
222
+```
223
+
224
+# リンク
225
+- [文字クラス](http://msdn.microsoft.com/ja-jp/library/20bw873z)
226
+
227
+- [文字列にUnicode固有文字が含まれるかのチェック方法: C#研究所](http://acha-ya.cocolog-nifty.com/blog/2010/12/unicode-ef79.html)
CSharp/NUnit/Home.md
... ...
@@ -0,0 +1,86 @@
1
+[[_TOC_]]
2
+~~#ls2~~
3
+
4
+# Visual Studio 設定
5
+- NUnit にパスが通っていること。
6
+- Visual C# 2010 Express だと、外部ツールとビルドイベントとでマクロの値が違うのはなんでなんだぜ。(--#)
7
+| | 外部ツール | ビルドイベント |
8
+| --- | --- | --- |
9
+| TargetPath | **obj**\Release\$(TargetName)$(TargetExt) | **bin**\Release\$(TargetName)$(TargetExt) |
10
+| TargetDir | **obj**\Release\ | **bin**\Release\ |
11
+| TargetName | (ターゲット名) | (ターゲット名) |
12
+| TargetExt | .exe または .dll | .exe または .dll |
13
+| TargetFileName | - | $(TargetName)$(TargetExt) |
14
+| BinDir | bin\Release\ | - |
15
+| OutDir | - | bin\Release\ |
16
+
17
+## 随時実行
18
+- 「ツール - 外部ツール」に追加する。
19
+| タイトル | NUnit(&U) |
20
+| --- | --- |
21
+| コマンド | nunit-console-x86.exe |
22
+| 引数 | "$(BinDir)$(TargetName)$(TargetExt)" |
23
+| 初期ディレクトリ | "$(BinDir)" |
24
+| 出力ウィンドウを使用 | チェックする |
25
+| 起動時に引数を入力 | チェックしない |
26
+| Unicodeで出力を処理する | チェックしない |
27
+- 単体テストのコードを含むプロジェクトを選択している状態で実行する。
28
+
29
+## ビルド時に自動実行
30
+- 単体テストのコードを含むプロジェクトのプロパティを開き、「ビルドイベント」で設定する。
31
+| ビルド後に実行するコマンドライン<br />(NUnit 2.x) | if "$(ConfigurationName)" == "Release" (<br />&nbsp; cd /d "$(TargetDir)"<br />&nbsp; if "$(PlatformName)" == "x64" (<br />&nbsp; &nbsp; nunit-console.exe "$(TargetPath)"<br />&nbsp; ) else if "$(PlatformName)" == "x86" (<br />&nbsp; &nbsp; nunit-console-x86.exe "$(TargetPath)"<br />&nbsp; ) else (<br />&nbsp; &nbsp; echo "NUnit skipped on platform: $(PlatformName)"<br />&nbsp; )<br />) |
32
+| --- | --- |
33
+| ビルド後に実行するコマンドライン<br />(NUnit 3.x) | if "$(ConfigurationName)" == "Release" (<br />&nbsp; cd /d "$(TargetDir)"<br />&nbsp; nunit3-console.exe "$(TargetPath)" --result="$(TargetName).xml"<br />) |
34
+| ビルド後に実行するコマンドライン<br />(NUnit 3.x + ReportUnit) | if "$(ConfigurationName)" == "Release" (<br />&nbsp; NUnit_Report "$(TargetDir)" "$(TargetPath)" "$(TargetName)"<br />) |
35
+| ビルド後イベントの実行 | ビルドがプロジェクト出力を更新したとき |
36
+
37
+### NUnit_Report.bat
38
+```dosbatch
39
+set TargetDir=%1
40
+set TargetPath=%2
41
+set TargetName=%3
42
+cd /d "%TargetDir%"
43
+nunit3-console.exe "%TargetPath%" --result="%TargetName%.xml"
44
+set ErrorCount=%ERRORLEVEL%
45
+ReportUnit "%TargetName%.xml"
46
+exit /b %ErrorCount%
47
+```
48
+
49
+# Link
50
+- http://www.nunit.org/
51
+ - [Classic Assert Model](http://www.nunit.org/index.php?p=classicModel&r=2.6.3)
52
+- [GitHub:nunit](https://github.com/nunit)
53
+ - [GitHub:nunit/nunit-framework](https://github.com/nunit/nunit-framework)
54
+ - [GitHub:nunit/nunit-console](https://github.com/nunit/nunit-console)
55
+
56
+- [C# Blog - Tips and Tricks: Integrate NUnit with Visual Studio Express](http://blog.megahard.info/2011/05/integrate-nunit-with-visual-studio.html)
57
+
58
+- [C#で始めるテスト駆動開発入門:CodeZine](http://codezine.jp/article/corner/446)
59
+ - [NUnitの全貌 ~ 基本から、最新バージョンの新機能まで:CodeZine](http://codezine.jp/article/detail/6518)
60
+ - [TDDで仕様変更とデバッグをする方法:CodeZine](http://codezine.jp/article/detail/6590)
61
+
62
+- [@IT:.NET Tools : テスト駆動開発ツール最前線(前編)](http://www.atmarkit.co.jp/fdotnet/tools/nunit22_01/nunit22_01_01.html)
63
+
64
+- [VisualC#2010ExpressにおけるNUnitの基本的な設定の仕方 - 森理 麟(moririring)のプログラマブログ](http://moririring.hatenablog.com/entry/20120928/1348782030)
65
+
66
+- [C# Expressで構成マネージャ - 隊長GAN-STのブログ](http://www.gan.st/gan/blog/index.php?itemid=3860)
67
+
68
+- [VB.NETとC#でデザインパターン](http://hccweb1.bai.ne.jp/tsune-1/)<br />
69
+**NUnitReport**: Nunit の nunit-console.exe で出力されたXMLテスト結果をHTML変換したレポートを作成します。
70
+
71
+- [ReportUnit](http://relevantcodes.com/reportunit-report-generator/)
72
+ - [NuGet Gallery - ReportUnit](https://www.nuget.org/packages/ReportUnit/)
73
+
74
+- [Differences between Assert.True and Assert.IsTrue in NUnit? - Stack Overflow](http://stackoverflow.com/questions/12352448/)
75
+- [c# - How to assert that two list contains elements with the same public properties in NUnit? - Stack Overflow](http://stackoverflow.com/questions/12171411/)
76
+
77
+# おまけ
78
+- マクロ値確認に使ったバッチファイル
79
+```dosbatch
80
+@echo off
81
+echo %cd%
82
+:loop
83
+echo %0
84
+shift
85
+if not '%0' == '' goto loop
86
+```
... ...
\ No newline at end of file
CSharp/NUnit/NUnit-VS-TagJump.md
... ...
@@ -0,0 +1,50 @@
1
+[[_TOC_]]
2
+
3
+- [GitHub:TakeAsh/cs-NUnit-VS-TagJump](https://github.com/TakeAsh/cs-NUnit-VS-TagJump)
4
+- [NUnit-VS-TagJump_exe.zip](NUnit-VS-TagJump_exe.zip)
5
+
6
+# 概要
7
+- Visual Studio でタグジャンプできるように NUnit の出力を整形するフィルタ。
8
+- "Test Failure" だけでなく "Test Error" および "Not Runnable" も捕捉する。
9
+
10
+# 使用法
11
+
12
+## ビルドイベント
13
+- ビルド後に実行するコマンドライン
14
+```
15
+if "$(ConfigurationName)" == "Release" (
16
+ cd /d "$(TargetDir)"
17
+ if "$(PlatformName)" == "x64" (
18
+ nunit-console.exe "$(TargetPath)" | NUnit-VS-TagJump.exe
19
+ ) else if "$(PlatformName)" == "x86" (
20
+ nunit-console-x86.exe "$(TargetPath)" | NUnit-VS-TagJump.exe
21
+ ) else (
22
+ echo "NUnit skipped on platform: $(PlatformName)"
23
+ )
24
+)
25
+```
26
+- ビルド後イベントの実行
27
+```
28
+ビルドがプロジェクト出力を更新したとき
29
+```
30
+
31
+## 外部ツール
32
+| Title | NUnit(&U) |
33
+| --- | --- |
34
+| Command | NUnit_VS.bat |
35
+| Arguments | "$(BinDir)" "$(BinDir)$(TargetName)$(TargetExt)" |
36
+| Initial directory | "$(BinDir)" |
37
+| use output window | check |
38
+| NUnit_VS.bat | @echo off<br />cd /d "%1"<br />nunit-console-x86.exe "%2" &#x7c; NUnit-VS-TagJump.exe |
39
+
40
+# 動作環境
41
+- NUnit 2.6.3
42
+- Visual Studio 2010 SP1
43
+- .NET framework 4.0
44
+
45
+# リンク
46
+- [時をかける旅人 » Blog Archive » VisualStudio2005+TestDriven.NETでタグジャンプ可能にする方法](http://banban55.dip.jp/~ragnarok/blog2/?p=109)
47
+
48
+- [カスタム ビルド ステップまたはビルド イベントの出力の書式設定](http://msdn.microsoft.com/ja-jp/library/yxkt8b26.aspx)
49
+
50
+- [標準入力(パイプ)からテキストを読み込むには?[C#、VB] - @IT](http://www.atmarkit.co.jp/fdotnet/dotnettips/681stdin/stdin.html)
... ...
\ No newline at end of file
CSharp/NuGet.md
... ...
@@ -0,0 +1,18 @@
1
+[[_TOC_]]
2
+
3
+# リンク
4
+- https://www.nuget.org/
5
+ - [Downloads](https://dist.nuget.org/index.html)
6
+
7
+# インストール
8
+- VS2013 より前のバージョンで使用する場合は、Commandline 版をダウンロードして適当なフォルダにコピーする。
9
+- 環境変数 Path に上記フォルダを追加する。(コマンドプロンプトの再起動後に反映される)
10
+- 最新版へ更新
11
+```
12
+> nuget update -self
13
+```
14
+
15
+# パッケージのインストール
16
+- カレントディレクトリにインストールされる。
17
+```
18
+> nuget install <パッケージ名>
... ...
\ No newline at end of file
CSharp/scanNetArp.md
... ...
@@ -0,0 +1,220 @@
1
+[[_TOC_]]
2
+
3
+# 概要
4
+- 指定した IPv4 ゾーンに対して MAC アドレスを収集するコマンドラインツール。
5
+- IP アドレスを指定しなかった場合は、自身のホストアドレスを元に収集する。
6
+- ファイアウォール等で ping 応答を返さない端末についても収集する。
7
+- 電源が落ちている端末については収集出来ない。
8
+- 要 .NET Framework 4.0
9
+
10
+# 実行ファイルのみ
11
+- [scanNetArp_bin.zip](scanNetArp_bin.zip)
12
+
13
+# ソース
14
+- [scanNetArp.zip](scanNetArp.zip)
15
+```csharp
16
+/**
17
+ @file Program.cs
18
+
19
+ @mainpage scan Net Arp
20
+ - 指定した IPv4 ゾーンに対して MAC アドレスを収集するコマンドラインツール。
21
+ - IP アドレスを指定しなかった場合は、自身のホストアドレスを元に収集する。
22
+ - ファイアウォール等で ping 応答を返さない端末についても収集する。
23
+ - 電源が落ちている端末については収集出来ない。
24
+ - 要 .NET Framework 4.0
25
+
26
+ - ARPによるMACアドレスの取得 @ SIN\@SAPPOROWORKSの覚書<br/>
27
+ http://d.hatena.ne.jp/spw0022/20111024/1319575443
28
+
29
+ - マルチスレッド @ ++C++;// 未確認飛行 C<br/>
30
+ http://ufcpp.net/study/csharp/sp_thread.html
31
+*/
32
+
33
+using System;
34
+using System.Collections.Generic;
35
+using System.Net;
36
+using System.Runtime.InteropServices;
37
+using System.Text.RegularExpressions;
38
+using System.Threading.Tasks;
39
+
40
+namespace TakeAsh.scanNetArp {
41
+ class Program {
42
+
43
+ /// <summary>
44
+ /// SendARP function<br/>
45
+ /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa366358.aspx
46
+ /// </summary>
47
+ /// <param name="dstIp">The destination IPv4 address</param>
48
+ /// <param name="srcIp">he source IPv4 address of the sender</param>
49
+ /// <param name="mac">A pointer to an array of ULONG variables</param>
50
+ /// <param name="macLen">a pointer to a ULONG value
51
+ /// that specifies the maximum buffer size, in bytes</param>
52
+ /// <returns>
53
+ /// - If the function succeeds, the return value is NO_ERROR.
54
+ /// - If the function fails, the return value is one of the following error codes.
55
+ /// </returns>
56
+ [DllImport("IPHlpApi.dll", ExactSpelling = true)]
57
+ private static extern uint SendARP(uint dstIp, uint srcIp, Byte[] mac, ref uint macLen);
58
+
59
+ /// <summary>
60
+ /// ステータスコードとシンボルの対応 (WinError.h)
61
+ /// </summary>
62
+ static Dictionary<uint, string> StatusCode = new Dictionary<uint, string>(){
63
+ { 0, "NO_ERROR" },
64
+ { 67, "ERROR_BAD_NET_NAME" },
65
+ { 111, "ERROR_BUFFER_OVERFLOW" },
66
+ { 31, "ERROR_GEN_FAILURE" },
67
+ { 87, "ERROR_INVALID_PARAMETER" },
68
+ { 1784, "ERROR_INVALID_USER_BUFFER" },
69
+ { 1168, "ERROR_NOT_FOUND" },
70
+ { 50, "ERROR_NOT_SUPPORTED" },
71
+ };
72
+
73
+ /// <summary>
74
+ /// IP アドレス最大値
75
+ /// </summary>
76
+ const int ipMax = 254;
77
+
78
+ /// <summary>
79
+ /// ARP問い合わせ結果を格納するためのクラス
80
+ /// </summary>
81
+ class ARPresult {
82
+
83
+ /// <summary>
84
+ /// IPアドレス
85
+ /// </summary>
86
+ public string ip;
87
+
88
+ /// <summary>
89
+ /// MACアドレス
90
+ /// </summary>
91
+ public Byte[] mac;
92
+
93
+ /// <summary>
94
+ /// MACアドレスのバイト数
95
+ /// </summary>
96
+ public uint macLen;
97
+
98
+ /// <summary>
99
+ /// ARP問い合わせ結果
100
+ /// </summary>
101
+ public uint status;
102
+ }
103
+
104
+ /// <summary>
105
+ /// ヘルプメッセージの表示および終了
106
+ /// </summary>
107
+ static void showHelpMessage() {
108
+ Console.WriteLine(
109
+ "usage: scanNetArp [aa.bb.cc.dd]\n" +
110
+ "listup MAC addresses in zone aa.bb.cc.xx or localnet."
111
+ );
112
+ Environment.Exit(-1);
113
+ }
114
+
115
+ /// <summary>
116
+ /// ARP 情報の収集を行う
117
+ /// </summary>
118
+ /// <param name="zone">対象ゾーン</param>
119
+ /// <returns>収集結果の配列</returns>
120
+ static ARPresult[] getArpTable(IPAddress zone) {
121
+ ARPresult[] results = new ARPresult[ipMax];
122
+ Byte[] zoneByte = zone.GetAddressBytes();
123
+
124
+ Parallel.For(0, ipMax, ip => {
125
+ ARPresult result = new ARPresult();
126
+ result.ip = string.Format("{0}.{1}.{2}.{3}",
127
+ zoneByte[0], zoneByte[1], zoneByte[2], ip + 1);
128
+ result.mac = new Byte[sizeof(uint) * 2];
129
+ result.macLen = (uint)result.mac.Length;
130
+ IPAddress dst = IPAddress.Parse(result.ip);
131
+ Console.Error.WriteLine(string.Format("Request:{0}", dst.ToString()));
132
+ Byte[] addrByte = dst.GetAddressBytes();
133
+ uint addr = 0;
134
+ for(int i = addrByte.Length - 1; i >= 0; --i) {
135
+ addr <<= 8;
136
+ addr |= addrByte[i];
137
+ }
138
+ result.status = SendARP(addr, 0, result.mac, ref result.macLen);
139
+ results[ip] = result;
140
+ });
141
+ Console.Error.WriteLine();
142
+
143
+ return results;
144
+ }
145
+
146
+ /// <summary>
147
+ /// ARP 情報の表示<br/>
148
+ /// 収集ステータスが NO_ERROR だったもののみを表示する。
149
+ /// </summary>
150
+ /// <param name="results">ARP 情報テーブル</param>
151
+ static void printArpTable(ARPresult[] results) {
152
+ Console.WriteLine("IPAddr\tMACAddr");
153
+ for(int ip = 0; ip < ipMax; ++ip) {
154
+ if(results[ip].status != 0) {
155
+ // NO_ERROR でなければスキップする
156
+ continue;
157
+ }
158
+ string macStr = "";
159
+ for(uint i = 0; i < results[ip].macLen; ++i) {
160
+ macStr += string.Format("{0:x2}:", results[ip].mac[i]);
161
+ }
162
+ /*
163
+ uint statusCode = results[ip].status;
164
+ var status = StatusCode.ContainsKey( statusCode )
165
+ ? StatusCode[statusCode]
166
+ : statusCode.ToString();
167
+ */
168
+ Console.WriteLine(string.Format("{0}\t{1}",
169
+ results[ip].ip, macStr.TrimEnd(':')));
170
+ }
171
+ Console.WriteLine();
172
+ }
173
+
174
+ static void Main(string[] args) {
175
+ IPAddress[] addrList = new IPAddress[] { new IPAddress(0) };
176
+ if(args.Length > 0) {
177
+ if(!IPAddress.TryParse(args[0], out addrList[0])) {
178
+ showHelpMessage();
179
+ } else {
180
+ Console.WriteLine("IPAddr:\t" + addrList[0].ToString());
181
+ }
182
+ } else {
183
+ string hostName = Dns.GetHostName();
184
+ Console.WriteLine("Host:\t" + hostName);
185
+ IPAddress[] addrV4V6List = Dns.GetHostAddresses(hostName);
186
+ List<IPAddress> addrV4List = new List<IPAddress>();
187
+ Regex regIPv4 = new Regex(@"^\d+\.\d+\.\d+\.\d+$");
188
+ for(int i = 0; i < addrV4V6List.Length; ++i) {
189
+ string addrStr = addrV4V6List[i].ToString();
190
+ if(regIPv4.IsMatch(addrStr)) {
191
+ addrV4List.Add(addrV4V6List[i]);
192
+ Console.WriteLine("IPAddr:\t" + addrStr);
193
+ }
194
+ }
195
+ addrList = addrV4List.ToArray();
196
+ }
197
+ Console.WriteLine("Date:\t" + DateTime.Now.ToString("G") + "\r\n");
198
+
199
+ foreach(IPAddress address in addrList) {
200
+ ARPresult[] results = getArpTable(address);
201
+ printArpTable(results);
202
+ }
203
+ }
204
+ }
205
+}
206
+```
207
+
208
+# リンク
209
+- [SendARP function](http://msdn.microsoft.com/en-us/library/windows/desktop/aa366358.aspx)
210
+
211
+- [SIN@SAPPOROWORKSの覚書](http://d.hatena.ne.jp/spw0022/)
212
+ - [ARPによるMACアドレスの取得](http://d.hatena.ne.jp/spw0022/20111024/1319575443)
213
+
214
+- [++C++;// 未確認飛行 C](http://ufcpp.net/)
215
+ - [マルチスレッド](http://ufcpp.net/study/csharp/sp_thread.html)
216
+
217
+- [株式会社リアライズ](http://www.e-realize.com/)
218
+ - [NetEnum](http://www.e-realize.com/netenum.html)
219
+
220
+- [Look@Lan](http://lookatlan.com/)
... ...
\ No newline at end of file
_Sidebar.md
... ...
@@ -1,5 +1,6 @@
1 1
- Programming
2 2
- [[Perl|/Perl/Home]]
3
+ - [[C#|/CSharp/Home]]
3 4
- [[JavaScript|/JavaScript/Home]]
4 5
- [[Windows|/Windows/Home]]
5 6
- [[Linux|/Linux/Home]]