とか言いつつ今日は暑いです。
えー、8月も間もなく終わり、前回のエントリからほぼ3週間ですか。思いの外サボってしまいました…。
そんな時期もありますよね(白目)。ボチボチいきます…。
とか言いつつ今日は暑いです。
えー、8月も間もなく終わり、前回のエントリからほぼ3週間ですか。思いの外サボってしまいました…。
そんな時期もありますよね(白目)。ボチボチいきます…。
public static void ByCounts(string path, int keepCount)
{
Directory.GetFiles(path)
.OrderByDescending(f => f)
.Skip(keepCount)
.ToList()
.ForEach(f => File.Delete(f));
}
ま、シンプルですよね。public static void BySize(string path, long size)
{
long totalSize = 0;
Directory.GetFiles(path)
.OrderByDescending(f => f)
.SkipWhile(f => (totalSize += new FileInfo(f).Length) < size)
.ToList()
.ForEach(f => File.Delete(f));
}
public static void ByDays(string path, int days, int startPos, string dateForm)
{
var target = DateTime.Today.AddDays(-days);
Directory.GetFiles(path)
.Where(f => DateTime.ParseExact(
Path.GetFileName(f).Substring(startPos, dateForm.Length),
dateForm,
System.Globalization.DateTimeFormatInfo.InvariantInfo) < target)
.ToList()
.ForEach(f => File.Delete(f));
}
DeleteOldLogFiles.ByDays(logFolderPath, 3, 4, "yyyy-MM-dd");
public class Dummy
{
private DataTable table;
public Dummy(DataTable table)
{
this.table = table;
}
public int SumOfQuantity
{
get
{
int sum = 0;
foreach (DataRow row in table.Rows)
{
sum += (int)row["qty"];
}
return sum;
}
}
public int FirstOrder
{
get { return (int)table.Rows[0]["order"]; }
}
public void SetDone()
{
foreach (var row in table.Rows.Cast<DataRow>().Where(r => (int)r["f"] == 0))
{
row["f"] = 1;
row["doneAt"] = DateTime.Now;
}
}
}
>"C:\Program Files\Microsoft Visual Studio 11.0\Team Tools\ Static Analysis Tools\FxCop\FxCopCmd.exe" /f:D:\Projects\Da taTableRuleDummy\bin\Debug\DataTableRuleDummy.dll /c
public class Dummy
{
private DataTable table;
public Dummy(DataTable table)
{
this.table = table;
}
public int SumOfQuantity
{
get { return table.AsEnumerable().Sum(r => r.Field<int>("qty")); }
}
public int FirstOrder
{
get { return table.AsEnumerable().First().Field<int>("order"); }
}
public void SetDone()
{
foreach (var row in table.Select("flag=0"))
{
row.SetField("flag", 1);
row.SetField("doneAt", DateTime.Now);
}
}
}
| イマイチ好みじゃない | ずいぶんマシ |
|---|---|
| foeach構文でDataTable.Rowsプロパティを使う。 | DataTable.AsEnumerable拡張メソッドまたはDataTable.Selectメソッドを使う。 |
| LINQを使うために、DataTable.RowsプロパティにEnumerable.Cast<DataRow>拡張メソッドを使う。 | DataTable.AsEnumerable拡張メソッドまたはDataTable.Selectメソッドを使う。 |
| DataRowCollectionクラスのインデクサを使う。 | DataTable.AsEnumerable拡張メソッドまたはDataTable.Selectメソッドを使う。(インデクサは使わない。) |
| DataRowクラスのインデクサを使う。 | DataRow.Field拡張メソッドとDataRow.SetField拡張メソッドを使う。 |
using Microsoft.FxCop.Sdk;
namespace DataTableRules
{
public abstract class BaseDataTableRule : BaseIntrospectionRule
{
protected BaseDataTableRule(string name) : base(
name, "DataTableRules.CustomRules", typeof(BaseDataTableRule).Assembly) {}
public override ProblemCollection Check(Member member)
{
var m = member as Method;
if (m != null)
Visit(m);
return Problems;
}
}
}
using System;
using Microsoft.FxCop.Sdk;
namespace DataTableRules
{
public class NoUseGetEnumeratorMethodToDataTableRows : BaseDataTableRule
{
public NoUseGetEnumeratorMethodToDataTableRows()
: base("NoUseGetEnumeratorMethodToDataTableRows") {}
public override void VisitMethodCall(MethodCall call)
{
var binding = call.Callee as MemberBinding;
var target = binding.TargetObject;
var member = binding.BoundMember;
if (member.Name.Name == "GetEnumerator" &&
target.Type.FullName == "System.Data.DataRowCollection")
{
Problems.Add(new Problem(GetResolution()));
}
base.VisitMethodCall(call);
}
}
}
using System;
using Microsoft.FxCop.Sdk;
namespace DataTableRules
{
public class NoUseCastMethodToDataTableRows : BaseDataTableRule
{
public NoUseCastMethodToDataTableRows()
: base("NoUseCastMethodToDataTableRows") {}
public override void VisitMethodCall(MethodCall call)
{
var binding = call.Callee as MemberBinding;
var member = binding.BoundMember;
if (member.FullName ==
"System.Linq.Enumerable.Cast<System.Data.DataRow>"
+ "(System.Collections.IEnumerable)")
{
Problems.Add(new Problem(GetResolution()));
}
base.VisitMethodCall(call);
}
}
}
using System;
using Microsoft.FxCop.Sdk;
namespace DataTableRules
{
public class NoUseIndexerToDataTableRows : BaseDataTableRule
{
public NoUseIndexerToDataTableRows()
: base("NoUseIndexerToDataTableRows") {}
public override void VisitMethodCall(MethodCall call)
{
var binding = call.Callee as MemberBinding;
var member = binding.BoundMember;
if (member.FullName.StartsWith(
"System.Data.DataRowCollection.get_Item(", StringComparison.Ordinal))
{
Problems.Add(new Problem(GetResolution()));
}
base.VisitMethodCall(call);
}
}
}
using System;
using Microsoft.FxCop.Sdk;
namespace DataTableRules
{
public class NoUseIndexerToDataRow : BaseDataTableRule
{
public NoUseIndexerToDataRow() : base("NoUseIndexerToDataRow") {}
public override void VisitMethodCall(MethodCall call)
{
var binding = call.Callee as MemberBinding;
var member = binding.BoundMember;
if (member.FullName.StartsWith(
"System.Data.DataRow.get_Item(", StringComparison.Ordinal) ||
member.FullName.StartsWith(
"System.Data.DataRow.set_Item(", StringComparison.Ordinal))
{
Problems.Add(new Problem(GetResolution()));
}
base.VisitMethodCall(call);
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<Rules FriendlyName="データテーブルの使い方の規則">
<Rule TypeName="NoUseCastMethodToDataTableRows"
Category="My.DataTable" CheckId="DT0001">
<Name>DataTable.RowsにCast<DataRow>()拡張メソッドを使用しません</Name>
<Description>可読性の向上のため、DataTable.RowsにCast<DataRow>拡張メソッド
を使用しません。</Description>
<Url />
<Resolution>DataTable.RowsにCast<DataRow>拡張メソッドが使用されています。
さらなる条件の絞り込みや、ソートが必要であればDataTable.Select()メソッドを、
そうでなければDataTable.AsEnumerable()拡張メソッドを使用してください。
</Resolution>
<Email />
<MessageLevel Certainty="80">Warning</MessageLevel>
<FixCategories>NonBreaking</FixCategories>
<Owner />
</Rule>
<Rule TypeName="NoUseGetEnumeratorMethodToDataTableRows"
Category="My.DataTable" CheckId="DT0002">
<Name>foreach構文でDataTable.Rowsを使用した列挙を行いません</Name>
<Description>LINQとの親和性向上のため、DataTable.Rows.GetEnumerable()メソッドを
使用しません。</Description>
<Url />
<Resolution>DataTable.Rows.GetEnumerable()が使用されています。さらなる条件の
絞り込みや、ソートが必要であればDataTable.Select()メソッドを、そうでなければ
DataTable.AsEnumerable()拡張メソッドを使用してください。</Resolution>
<Email />
<MessageLevel Certainty="80">Warning</MessageLevel>
<FixCategories>NonBreaking</FixCategories>
<Owner />
</Rule>
<Rule TypeName="NoUseIndexerToDataTableRows"
Category="My.DataTable" CheckId="DT0003">
<Name>DataTable.Rowsのインデクサを使用しません</Name>
<Description>可読性の向上のため、DataTable.Rowsのインデクサを使用しません。
</Description>
<Url />
<Resolution>DataTable.Rowsのインデクサが使用されています。テーブル内の各行を列挙
する場合には、DataTable.Select()メソッド、またはDataTable.AsEnumerable()拡張
メソッドを使用してforeach構文で列挙してください。 先頭行のみ取り出す場合には、
DataTable.AsEnumerable()拡張メソッドと、Enumerable.First()を使用して一時変数に
代入後、使用してください。
例:var firstRow = dt.AsEnumerable().First();</Resolution>
<Email />
<MessageLevel Certainty="80">Warning</MessageLevel>
<FixCategories>NonBreaking</FixCategories>
<Owner />
</Rule>
<Rule TypeName="NoUseIndexerToDataRow"
Category="My.DataTable" CheckId="DT0004">
<Name>DataRowのインデクサを使用しません</Name>
<Description>可読性の向上のため、DataRowのインデクサを使用しません。
</Description>
<Url />
<Resolution>DataRowのインデクサが使用されています。テーブル内の各行のカラムに値
を設定、または取得する場合は、DataRow.SetField<T>()拡張メソッド、および
DataRow.Field<T>()拡張メソッドを使用してください。</Resolution>
<Email />
<MessageLevel Certainty="80">Warning</MessageLevel>
<FixCategories>NonBreaking</FixCategories>
<Owner />
</Rule>
</Rules>
今週も色々面白かった。中でも出色は「さよならタマちゃん」最終回でした。
この漫画、連載開始当初はまるで期待せずに読んでたんですが、途中から格段に面白くなってきて、ここしばらくはとても楽しみにしていました。絵も好みです。
で、今回の最終回。電車のなかで読んだんですが、感情の起伏が激しくて、泣きそうになるのを我慢しながら読んでました。
しかし、漫画読んで泣くなんて久しぶり。記憶にある限りだと、「赤ちゃんと僕」以来。多分。
イブニングで25回の連載。ということは、ほぼ一年連載してたんですね。お疲れ様でした。
さて。次はどんな漫画を読ませてもらえるのか。楽しみに待ちまーす。
| イマイチ好みじゃない | ずいぶんマシ |
|---|---|
| foeach構文でDataTable.Rowsプロパティを使う。 | DataTable.AsEnumerable拡張メソッドまたはDataTable.Selectメソッドを使う。 |
| LINQを使うために、DataTable.Rows拡張プロパティにEnumerable.Cast<DataRow>拡張メソッドを使う。 | DataTable.AsEnumerable拡張メソッドまたはDataTable.Selectメソッドを使う。 |
| DataRowCollectionクラスのインデクサを使う。 | DataTable.AsEnumerable拡張メソッドまたはDataTable.Selectメソッドを使う。(インデクサは使わない。) |
| DataRowクラスのインデクサを使う。 | DataRow.Field拡張メソッドとDataRow.SetField拡張メソッドを使う。 |
foreach (DataRow row in table.Rows)
{
sum += (int)row["order"];
row["flag"] = 0;
row["doneAt"] = DateTime.Now;
}
foreach (var row in table.AsEnumerable())
{
sum += row.Field<int>("order");
row.SetField("flag", 0);
row.SetField("doneAt", DateTime.Now);
}
data.order = (int)table.Rows[0]["order"]; data.name = (string)table.Rows[0]["name"]; data.flag = (int)table.Rows[0]["flag"];
var firstRow = table.AsEnumerable().First();
data.order = firstRow.Field<int>("order");
data.name = firstRow.Field<string>("name");
data.flag = firstRow.Field<int>("flag");
public static IEnumerable<string> GetLineEnumerator(this TextReader tr)
{
string s;
while ((s = tr.ReadLine()) != null)
{
yield return s;
}
}
public static void WriteLines(
this TextWriter tw, IEnumerable<string> values)
{
foreach (var line in values)
{
tw.WriteLine(line);
}
}
static void Main(string[] args)
{
using(var reader = new StreamReader(args[0]))
{
Console.Out.WriteLines(Enumerable.Range(1, int.MaxValue)
.Zip(reader.GetLineEnumerator(), Tuple.Create)
.Select(x => string.Format("{0}:{1}", x.Item1, x.Item2)));
}
}
public static IEnumerable<string> GetLineEnumerator(this TextReader tr)
{
string s;
while ((s = tr.ReadLine()) != null)
{
yield return s;
}
}
public static void WriteLines(
this TextWriter tw, IEnumerable<string> values)
{
foreach (var line in values)
{
tw.WriteLine(line);
}
}
using (var sr = new StreamReader(inFile, Encoding.GetEncoding("shift-jis")))
using (var sw = new StreamWriter(outFile))
{
sw.WriteLines(sr.GetLineEnumerator()
.Select(line => line.Split(','))
.Where(items => int.Parse(items[0]) % 2 != 0)
.Select(items => string.Join(",", items.Select(item => item.Trim()))));
}
namespace Xxx.Yyy.Zzz
{
using System;
using System.Collections.Generic;
using System.Linq;
public class TheClass
{
}
}
if (condition())
return false;
| FxCop | StyleCop | |
|---|---|---|
| 目的 | アセンブリが「クラスライブラリのデザインガイドライン」に適合し、利用者から見てAPIに一貫性と使いやすさが備わっているかを分析する。 | ソースコードが一定のルールに基づいて、統一的な記述がなされているかを分析する。(空白や改行の入れ方、括弧の位置、記述の順番など) |
| 分析対象 | アセンブリ(IL:中間言語) | C# ソースコード |
| VisualStudioバンドル | Premium/Ultimate | なし |
| VisualStudio統合 | Premium/Ultimateはビルド統合済み。 Standardは別途ツールをインストールすることで呼び出し可能になる。 Expressでは基本的にFxCopを単体で稼働させる。 | Standard以上で可能。ただし、すべてのエディションでcsprojファイルの編集により、ビルドプロセス統合は可能。 |
| カスタムルールの作成 | 可能 | 可能 |
すべての流れをぶった切って、今週のモーニングについて。
相変わらず絶好調のモーニングですが、今は「カレチ」がとても悲しく、面白い。
「カレチ」は、JRの前身である「国鉄」において、諸々発生する問題を、現場の人たちの丁寧な、誠実な仕事で解決する。というお話で、鉄への愛と国鉄職員への愛で溢れている良作です。今週は最終章、5週連続掲載の2週目。
「国鉄」の「最後」の話。ということで、分割民営化が今描かれています。そして主人公の荻野は民営化前の、リストラの嵐に巻き込まれていきそうです。
今週の話を読んで思ったことをネタバレにならない程度にちょっとだけ言うと、現場で個人個人がどんだけ丁寧な仕事をしたって、組織というのは腐る。大きければ大きいほど腐りやすい。ということ。
それと、何話前だったかに舞台が現在に飛び、偏屈そうなジーさんになった荻野が登場していましたが、今の話があれに繋がるんだろうなぁ。と思うと…。やるせないなー。
楽しみにしていたお話が、あと3週で終わりを迎え、どうにもハッピーエンドは迎えられそうにない雰囲気。作者さんの力量もあり、とても面白いんですが切ないですね。
型無しデータセットを使う場合は、コードのメンテナンシビリティを保つために、以下の2つを守ることがおススメです。
- foeach構文でDataTable.Rowsプロパティを使わない。代わりにDataTable.AsEnumerable拡張メソッドを使う。
- DataRowクラスのインデクサを使わない。代わりにDataRow.Field拡張メソッドとDataRow.SetField拡張メソッドを使う。
using (var conn = new SqlConnection(connectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = selectCmd;
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
xxx = reader[columnName];
// いろいろ処理
}
}
}
んむー。せめてwhileじゃなくてforeachを使いたい。できればLINQに繋げたい。そのためには、SELECTの結果のレコードを、IEnumerable<T>で取得できるようなメソッドを用意しておきたい。そこで、DbCommandクラスにこんな拡張メソッドを用意してみます。なお、わかりやすくするためにパラメータのNULLチェックはなしで。public static IEnumerable<IDataRecord> ExecuteQuery(this DbCommand command)
{
return ExecuteQuery(command, dr => dr);
}
public static IEnumerable<T> ExecuteQuery<T>(
this DbCommand command, Func<IDataRecord, T> mapper)
{
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
yield return mapper(reader);
}
}
}
「ExecuteQuery」という名前の2つの拡張メソッドを作ります。一つはIEnumerable<IDataRecord>を返し、もう一方は任意の変換関数を用意して、IEnumerbale<T>を返します。ちなみに「IDataRecord」はDbCommand.ExecuteReaderメソッドが返す、DbDataReader抽象クラスの派生クラスで実装されます。const string connectionString =
@"Data Source=.\SQLEXPRESS;Initial Catalog=Test;Integrated Security=True";
const string selectCmd =
"select id, uid, insertAt, qty from TestTable_1 where exported=0";
const string updateCmd =
"update TestTable_1 set exported=1, exportAt=getdate() where id in ({0})";
static void Main(string[] args)
{
using (var conn = new SqlConnection(connectionString))
{
var ids = new List<int>();
using (var cmd = conn.CreateCommand())
using (var csv = new StreamWriter("output.csv"))
{
conn.Open();
cmd.CommandText = selectCmd;
foreach (var r in cmd.ExecuteQuery())
{
ids.Add(r.GetInt32(0));
csv.WriteLine(string.Format("{0},{1},{2}", r[1], r[2], r[3]));
}
}
if (ids.Count > 0)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = string.Format(updateCmd, string.Join(",", ids));
cmd.ExecuteNonQuery();
}
}
}
}
意外と見やすいコードが書けるんじゃないかと思ってるんですが、どうでしょ?DataTable t = GetTable();
foreach (var row in t.AsEnumerable().OrderBy(r => r.Field<string>("Kana")))
{
var name = row.Field<string>("Name");
var birthday = row.Field<DateTime?>("Birthday");
// name,birthdayを使っていろいろ処理
}
このコードは、当然Selectメソッドで匿名クラスを作ったりしても問題なく行けます。個人的は「これなら使ってもいっか。」という気になります。
static string GetNumberedUniqueFilename(string filename)
{
if (!File.Exists(filename))
return filename;
string d = Path.GetDirectoryName(filename),
fn = Path.GetFileNameWithoutExtension(filename),
ext = Path.GetExtension(filename);
for (int i = 2; ; ++i)
{
var f = Path.Combine(d, string.Format("{0} ({1}){2}", fn, i, ext));
if (!File.Exists(f))
return f;
}
}
static string GetNumberedUniqueFilename(string filename)
{
if (!File.Exists(filename))
return filename;
string d = Path.GetDirectoryName(filename),
fn = Path.GetFileNameWithoutExtension(filename),
ext = Path.GetExtension(filename);
return Enumerable.Range(2, int.MaxValue - 2)
.Select(i => Path.Combine(d, string.Format("{0} ({1}){2}", fn, i, ext)))
.SkipWhile(f => File.Exists(f))
.First();
}
int[] numbers = new[] { 0, 1, 2, 3, 4 };
string[] names = new[] { "Zero", "One", "Two", "Three", "Four" };
for (int i = 0; i < numbers.Length; ++i)
{
Console.WriteLine("{0}:{1}", numbers[i], names[i]);
}
int[] numbers = new[] { 0, 1, 2, 3, 4 };
string[] names = new[] { "Zero", "One", "Two", "Three", "Four" };
foreach (var x in numbers.Zip(names, Tuple.Create))
{
Console.WriteLine("{0}:{1}", x.Item1, x.Item2);
}
int[] numbers = new[] { 0, 1, 2, 3, 4 };
string[] names = new[] { "Zero", "One", "Two", "Three", "Four" };
foreach (var x in numbers.Zip(names, (number, name) => new { number, name }))
{
Console.WriteLine("{0}:{1}", x.number, x.name);
}
class ComparisonComparer<T> : IComparer<T>
{
private Comparison<T> comparison;
public ComparisonComparer(Comparison<T> comparison)
{
this.comparison = comparison;
}
public int Compare(T p1, T p2)
{
return comparison(p1, p2);
}
}
var dic = new SortedDictionary<string, int>(
new ComparisonComparer<string>((p1, p2) => string.Compare(p1, p2)));
static string MD5OldStyle(byte[] tgt)
{
var sb = new StringBuilder();
using (var md5 = MD5.Create())
{
foreach (var b in md5.ComputeHash(tgt))
{
sb.Append(b.ToString("x2"));
}
return sb.ToString();
}
}
static string MD5NewStyle(byte[] tgt)
{
using(var md5 = MD5.Create())
{
return string.Concat(md5.ComputeHash(tgt).Select(b => b.ToString("x2")));
}
}
var output = string.Concat(input.Where(c => Char.IsDigit(c)));
public void SetValidChars(CharType type, string option)
{
var validChars = new List<char>();
if (type == CharType.AllAscii)
validChars.AddRange(Enumerable.Range(0x20, 0x7f - 0x20)
.Select(n => Convert.ToChar(n)));
else if (type == CharType.NumericOnly)
validChars.AddRange("0123456789");
else if (type == CharType.Optional)
validChars.AddRange(option);
// この後、validCharsを使ってごにょごにょ
}
public sealed class String : IComparable, ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>
private static void Main(string[] args)
{
using (Bitmap bmp = new Bitmap(args[0]))
{
foreach (PropertyItem pr in bmp.PropertyItems)
{
Console.Write("ID=0x{0:X}({1}), Len={2}, Type={3}({4})",
pr.Id,
PropertyItemReader.GetExifTagId(pr.Id),
pr.Len,
pr.Type,
PropertyItemReader.GetExifType(pr.Type));
if (pr.Len > 0 && pr.Type == 2)
{
Console.WriteLine(", Value={0}",
PropertyItemReader.ReadStringValue(pr));
}
else if (pr.Len > 0 && new short[] {3,4,5,9,10}.Contains(pr.Type))
{
Console.WriteLine(", Value={0}", string.Join(",",
PropertyItemReader.ReadValues(pr).Cast<object>()));
}
else
{
Console.WriteLine("");
}
}
}
}
public class SwitchAction<T>
{
private List<Tuple<Func<T, bool>, Action<T>>> switches;
private Action<T> actionDefault = _ => { };
public SwitchAction()
{
switches = new List<Tuple<Func<T, bool>, Action<T>>>();
}
public SwitchAction(Action<T> actionDefault) : this()
{
this.actionDefault = actionDefault;
}
public void AddCase(Func<T, bool> condition, Action<T> action)
{
switches.Add(Tuple.Create(condition, action));
}
public void Action(T target)
{
var sw = switches.FirstOrDefault(s => s.Item1(target));
if (sw != null)
sw.Item2(target);
else
actionDefault(target);
}
}
private static void Main(string[] args)
{
using (Bitmap bmp = new Bitmap(args[0]))
{
var sw = new SwitchAction<PropertyItem>(_ => Console.WriteLine());
sw.AddCase(p => p.Len > 0 && p.Type == 2,
p => Console.WriteLine(", Value={0}",
PropertyItemReader.ReadStringValue(p)));
sw.AddCase(p => p.Len > 0 && new short[] {3,4,5,9,10}.Contains(p.Type),
p => Console.WriteLine(", Value={0}",
string.Join(",", PropertyItemReader.ReadValues(p).Cast<object>())));
foreach (PropertyItem property in bmp.PropertyItems)
{
Console.Write("ID=0x{0:X}({1}), Len={2}, Type={3}({4})",
property.Id,
PropertyItemReader.GetExifTagId(property.Id),
property.Len,
property.Type,
PropertyItemReader.GetExifType(property.Type));
sw.Action(property);
}
}
}
public class SwitchFunc<T, TResult>
{
private List<Tuple<Func<T, bool>, Func<T, TResult>>> switches;
private Func<T, TResult> funcDefault = _ => default(TResult);
public SwitchFunc()
{
switches = new List<Tuple<Func<T, bool>, Func<T, TResult>>>();
}
public SwitchFunc(TResult resultDefault) : this()
{
this.funcDefault = _ => resultDefault;
}
public SwitchFunc(Func<T, TResult> funcDefault) : this()
{
this.funcDefault = funcDefault;
}
public void AddCase(Func<T, bool> condition, Func<T, TResult> func)
{
switches.Add(Tuple.Create(condition, func));
}
public TResult Func(T target)
{
var sw = switches.FirstOrDefault(s => s.Item1(target));
if (sw != null)
return sw.Item2(target);
else
return funcDefault(target);
}
}
private static void Main(string[] args)
{
using (Bitmap bmp = new Bitmap(args[0]))
{
var sw = new SwitchFunc<PropertyItem, string>(string.Empty);
sw.AddCase(p => p.Len > 0 && p.Type == 2,
p => ", Value=" +
PropertyItemReader.ReadStringValue(p));
sw.AddCase(p => p.Len > 0 && new short[] {3,4,5,9,10}.Contains(p.Type),
p => ", Value=" +
string.Join(",", PropertyItemReader.ReadValues(p).Cast<object>()));
Array.ForEach(bmp.PropertyItems, p =>
Console.WriteLine("ID=0x{0:X}({1}), Len={2}, Type={3}({4}){5}",
p.Id,
PropertyItemReader.GetExifTagId(p.Id),
p.Len,
p.Type,
PropertyItemReader.GetExifType(p.Type),
sw.Func(p)));
}
}
private static void Main(string[] args)
{
using (Bitmap bmp = new Bitmap(args[0]))
{
Array.ForEach(bmp.PropertyItems, p =>
Console.WriteLine("ID=0x{0:X}({1}), Len={2}, Type={3}({4}){5}",
p.Id,
PropertyItemReader.GetExifTagId(p.Id),
p.Len,
p.Type,
PropertyItemReader.GetExifType(p.Type),
p.Len > 0 && p.Type == 2 ?
", Value=" + PropertyItemReader.ReadStringValue(p) :
p.Len > 0 && new short[] {3,4,5,9,10}.Contains(p.Type) ?
", Value=" + string.Join(",",
PropertyItemReader.ReadValues(p).Cast<object>()) : ""));
}
}
private static void Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine("Less Arguments.");
return;
}
try
{
using (Bitmap bmp = new Bitmap(args[0]))
{
Func<PropertyItem, string> getvalues = p =>
p.Len > 0 && p.Type == 2 ?
", Value=" + PropertyItemReader.ReadStringValue(p) :
p.Len > 0 && new short[] {3,4,5,9,10}.Contains(p.Type) ?
", Value=" + string.Join(",",
PropertyItemReader.ReadValues(p).Cast<object>()) : "";
Array.ForEach(bmp.PropertyItems, p =>
Console.WriteLine("ID=0x{0:X}({1}), Len={2}, Type={3}({4}){5}",
p.Id,
PropertyItemReader.GetExifTagId(p.Id),
p.Len,
p.Type,
PropertyItemReader.GetExifType(p.Type),
getvalues(p)));
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
private static void Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine("Less Arguments.");
return;
}
try
{
using (Bitmap bmp = new Bitmap(args[0]))
{
foreach (PropertyItem pr in bmp.PropertyItems)
{
Console.Write("ID=0x{0:X}({1}), Len={2}, Type={3}({4})",
pr.Id,
PropertyItemReader.GetExifTagId(pr.Id),
pr.Len,
pr.Type,
PropertyItemReader.GetExifType(pr.Type));
if (pr.Len > 0)
{
if (pr.Type == 2)
{
Console.WriteLine(", Value={0}",
PropertyItemReader.ReadStringValue(pr));
}
else if (pr.Type == 3 || pr.Type == 4 || pr.Type == 5 ||
pr.Type == 9 || pr.Type == 10)
{
StringBuilder sb = new StringBuilder();
foreach (object o in PropertyItemReader.ReadValues(pr))
{
sb.Append(o.ToString());
sb.Append(",");
}
sb.Remove(sb.Length - 1, 1);
Console.WriteLine(", Value={0}", sb.ToString());
}
else
{
Console.WriteLine("");
}
}
else
{
Console.WriteLine("");
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
ちなみに、実行するとこんな結果を吐き出します。
private static void Main(string[] args)
{
using (Bitmap bmp = new Bitmap(args[0]))
{
foreach (PropertyItem pr in bmp.PropertyItems)
{
Console.Write("ID=0x{0:X}({1}), Len={2}, Type={3}({4})",
pr.Id,
PropertyItemReader.GetExifTagId(pr.Id),
pr.Len,
pr.Type,
PropertyItemReader.GetExifType(pr.Type));
if (pr.Len > 0 && pr.Type == 2)
{
Console.WriteLine(", Value={0}",
PropertyItemReader.ReadStringValue(pr));
}
else if (pr.Len > 0 && new short[] {3,4,5,9,10}.Contains(pr.Type))
{
Console.WriteLine(", Value={0}", string.Join(",",
PropertyItemReader.ReadValues(pr).Cast<object>()));
}
else
{
Console.WriteLine("");
}
}
}
}
public static StringDictionary
GetNodeNamespaces(XmlNode node, string defaultNSSubstitute)
{
// 名前空間用辞書オブジェクトの生成
StringDictionary namespaces = new StringDictionary();
// 対象XMLノードからXML属性コレクションを取得
XmlAttributeCollection attribs = node.Attributes;
// XML属性すべてについて
foreach (XmlAttribute attrib in attribs)
{
// "xmlns"で始まる場合
if (attrib.Name.StartsWith("xmlns"))
{
string prefix = null;
// デフォルトの名前空間の場合
if (attrib.Name == "xmlns")
{
// 代替が指定されていれば代替文字列をプリフィクスにして登録
if (!string.IsNullOrEmpty(defaultNSSubstitute))
prefix = defaultNSSubstitute;
else
prefix = string.Empty;
}
// デフォルト以外の場合
else if (attrib.Name[5] == ':' && attrib.Name.Length > 6)
prefix = attrib.Name.Substring(6);
// 名前空間用辞書にプリフィクスと名前空間のペアを追加
if (prefix != null)
{
namespaces.Add(prefix, attrib.Value);
}
}
}
return namespaces;
}
public static Dictionary<string, string>
GetNodeNamespaces(XmlNode node, string defaultNSSubstitute)
{
var namespaces = new Dictionary<string string>();
foreach (var attrib in node.Attributes.Cast<XmlAttribute>()
.Where(a => a.Name.StartsWith("xmlns")))
{
string prefix = null;
if (attrib.Name == "xmlns")
{
if (!string.IsNullOrEmpty(defaultNSSubstitute))
prefix = defaultNSSubstitute;
else
prefix = string.Empty;
}
else if (attrib.Name[5] == ':' && attrib.Name.Length > 6)
prefix = attrib.Name.Substring(6);
if (prefix != null)
{
namespaces.Add(prefix, attrib.Value);
}
}
return namespaces;
}
public static Dictionary<string, string>
GetNodeNamespaces(XmlNode node, string defaultNSSubstitute)
{
var defprefix = defaultNSSubstitute ?? string.Empty;
var namespaces = new Dictionary<string, string>();
foreach (var attrib in node.Attributes.Cast<XmlAttribute>()
.Where(a => a.Name.StartsWith("xmlns")))
{
string prefix = null;
if (attrib.Name == "xmlns")
prefix = defprefix;
else if (attrib.Name[5] == ':' && attrib.Name.Length > 6)
prefix = attrib.Name.Substring(6);
if (prefix != null)
{
namespaces.Add(prefix, attrib.Value);
}
}
return namespaces;
}
public static Dictionary<string, string>
GetNodeNamespaces(XmlNode node, string defaultNSSubstitute)
{
var defprefix = defaultNSSubstitute ?? string.Empty;
var namespaces = new Dictionary<string, string>();
foreach (var attrib in node.Attributes.Cast<XmlAttribute>()
.Where(a => a.Name == "xmlns" || a.Name.StartsWith("xmlns:")))
{
string prefix = null;
if (attrib.Name == "xmlns")
prefix = defprefix;
else
prefix = attrib.Name.Substring(6);
namespaces.Add(prefix, attrib.Value);
}
return namespaces;
}
public static Dictionary<string, string>
GetNodeNamespaces(XmlNode node, string defaultNSSubstitute)
{
var defprefix = defaultNSSubstitute ?? string.Empty;
var namespaces = new Dictionary<string, string>();
foreach (var attrib in node.Attributes.Cast<XmlAttribute>()
.Where(a => a.Name == "xmlns" || a.Name.StartsWith("xmlns:")))
{
namespaces.Add(attrib.Name == "xmlns" ?
defprefix : attrib.Name.Substring(6), attrib.Value);
}
return namespaces;
}
こうなると、IEnumerable<T>をDictionaryに変換しているだけなので、public static Dictionary<string string>
GetNodeNamespaces(XmlNode node, string defaultNSSubstitute)
{
var defprefix = defaultNSSubstitute ?? string.Empty;
return node.Attributes.Cast<xmlattribute>()
.Where(a => a.Name == "xmlns" || a.Name.StartsWith("xmlns:"))
.ToDictionary(a => a.Name == "xmlns" ?
defprefix : a.Name.Substring(6), a => a.Value);
}
var sb = new StringBuilder();
string line;
using (var sr = new StreamReader(inFile, Encoding.GetEncoding("shift-jis")))
using (var sw = new StreamWriter(outFile))
{
while ((line = sr.ReadLine()) != null)
{
var items = line.Split(',');
sb.Length = 0;
if (int.Parse(items[0]) % 2 != 0)
{
foreach (var item in items)
{
sb.Append(item.Trim()).Append(',');
}
sw.WriteLine(sb.ToString(0, sb.Length - 1));
}
}
}
var sb = new StringBuilder();
using (var sr = new StreamReader(inFile, Encoding.GetEncoding("shift-jis")))
using (var sw = new StreamWriter(outFile))
{
sw.WriteLines(sr.GetLineEnumerator()
.Select(line => line.Split(','))
.Where(items => int.Parse(items[0]) % 2 != 0)
.Select(items => sb.Clear().AppendAll(
items.Select(i => i.Trim() + ",")).ToString(0, sb.Length - 1)));
}
public static IEnumerable<string> GetLineEnumerator(this TextReader tr)
{
string s;
while ((s = tr.ReadLine()) != null)
{
yield return s;
}
}
public static void WriteLines(
this TextWriter tw, IEnumerable<string> values)
{
foreach (var line in values)
{
tw.WriteLine(line);
}
}
public static StringBuilder AppendAll(
this StringBuilder sb, IEnumerable<string> values)
{
foreach (var item in values)
{
sb.Append(item);
}
return sb;
}
using (var reader = new StreamReader(inFile))
{
return reader.GetLineEnumerator().ToArray();
}
using (var writer = new StreamWriter(outFile))
{
writer.WriteLines(lines);
}
using (var reader = new StreamReader(netstream))
using (var writer = new StreamWriter(outFile))
{
writer.WriteLines(reader.GetLineEnumerator());
}
string valueKey1 = null;
foreach (string query in uri.Query.Split('&')) // uriはUriオブジェクト
{
string[] kv = query.Split('=');
if (kv.Length < 2)
continue;
if (kv[0].StartsWith("?"))
kv[0] = kv[0].Substring(1);
if (kv[0] == "key1")
{
valueKey1 = kv[1];
break;
}
}
public static class UriExtensions
{
public static string FindQuery(this Uri uri, string key)
{
return FindQuery(uri, key, true);
}
public static string FindQuery(this Uri uri, string key, bool uriEscape)
{
throw new NotImplementedException();
}
}
[TestClass]
public class UriExtensionsTest
{
[TestMethod]
public void FindParamValueTest()
{
Uri u1 = new Uri("http://unkkown/test.html");
Assert.IsNull(u1.FindQuery("unknownkey"));
Uri u2 = new Uri("http://unknown/test.html?key1=xxx&key2=yyy&key3=zzz");
Assert.IsNull(u2.FindQuery("key4"));
Assert.AreEqual("yyy", u2.FindQuery("key2"));
string key = "%E3%82%AD%E3%83%BC"; // "キー"のURIエンコード(UTF-8)
string value = "%E5%80%A4"; // "値"のURIエンコード(UTF-8)
Uri u3 = new Uri("http://unknown/test.html?" + key + "=" + value);
Assert.AreEqual("値", u3.FindQuery("キー"));
Assert.AreEqual(value, u3.FindQuery(key, false));
}
}
public static class UriExtensions
{
public static string FindQuery(this Uri uri, string key)
{
return FindQuery(uri, key, true);
}
public static string FindQuery(this Uri uri, string key, bool uriEscape)
{
string query = uri.Query;
string keyName = uriEscape ? Uri.EscapeDataString(key) : key;
Func<string, string> vconv = s => s;
if (string.IsNullOrEmpty(query))
return null;
if (query.StartsWith("?"))
query = query.Substring(1);
if (uriEscape)
vconv = s => Uri.UnescapeDataString(s);
return query.Split('&').Where(q => q.StartsWith(keyName + "="))
.Select(q => vconv(q.Substring(keyName.Length + 1)))
.FirstOrDefault();
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace GetTotal
{
class Program
{
static void Main(string[] args)
{
if(args.Length < 1)
{
Console.Error.WriteLine("Less argument.");
return;
}
try
{
Func<string, long> gettotal = null;
gettotal = p =>
Directory.GetDirectories(p).Select(f => gettotal(f)).Sum() +
Directory.GetFiles(p).Select(f => new FileInfo(f).Length).Sum();
Console.WriteLine("Size: {0:#,0} Bytes", gettotal(args[0]));
}
catch(Exception e)
{
Console.Error.WriteLine(e.Message);
}
}
}
}
Func<string, long> gettotal = p =>
Directory.GetDirectories(p).Select(f => gettotal(f)).Sum() +
Directory.GetFiles(p).Select(f => new FileInfo(f).Length).Sum();