スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[C#] Exifライブラリを公開します。

コードを整理してたら、C#で作ったExifライブラリを見つけたw
いつの間にこんなの作ってたんだ??
しかも、結構作り込んでる。。。
なので、githubに公開します。
https://github.com/ss9/samplecode/tree/master/CS/Exif

どこかのコピペかな? コピペだったらごめんなさい。

中身はあまり確認していないので、使用する場合は自己責任でお願いします。
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

[C#]BitmapからGraphicsの取得

いつも忘れちゃうので。

Bitmap bmp = new Bitmap("bitmap.bmp");
Graphics graphics = Graphics.FromImage(bmp);

終わり。

テーマ : プログラミング
ジャンル : コンピュータ

[C#] ToolStripコントロールのInvokeの使い方

.NET開発(C#)で、Invokeでハマったのでメモします。

ハマった部分は、form以外のクラスから別スレッドを作り、
そのスレッドから、formのToolStrip系のコントロールを操作するところです。


別スレッドからフォーム上のコントロールを操作すると、適切な処理をしていないと、

InvalidOperationExceptionはハンドルされませんでした。
有効ではないスレッド間の操作:
コントロールが作成されたスレッド以外のスレッドからコントロール '' がアクセスされました。


みたいなエラーが出ます。

別スレッドから、コントロールを操作するには、
コントロールのInvokeを取得し、delegateにて操作します。
しかしToolStripProgressBarやToolStripStatusLabelに関しては、Invokeが取得できません。
よって、そのオーナを取得してInvokeを取得します。

色々試したので、下記にサンプルを書きます。
このサンプルは、カウンターを別スレッドで動かして、
TextBox, ToolStripProgressBar, ToolStripStatusLabelの値を変更しています。

invokesample1.jpg

Form1.cs


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication1 {
public partial class Form1 : Form {

// スレッドの作成
Thread _thread;
private delegate void SetValue(int val);

public Form1() {
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e) {
_thread = new Thread(new ThreadStart(formInvokeCounter));
_thread.Start();
}

private void button2_Click(object sender, EventArgs e) {
toolStripProgressBar1.Value = 0;
_thread = new Thread(new ThreadStart(controlInvokeCounter));
_thread.Start();
}

// このファンクションを別スレッドで動作させると、
// invokeしてないためエラーが発生します。
private void errorCounter() {
for (int i = 0; i <= 100; i++) {
textBox1.Text = i.ToString();
toolStripProgressBar1.Value = i;
toolStripStatusLabel1.Text = i.ToString();
Thread.Sleep(100);
}
}

// フォームまるごとInvokeします。
    // フォームのコントロールが取得できる場合に有効です。
private void formInvokeCounter() {
for (int i = 0; i <= 100; i++) {
this.Invoke(new SetValue(delegate(int val) {
textBox1.Text = val.ToString();
toolStripProgressBar1.Value = val;
toolStripStatusLabel1.Text = val.ToString();
}), i);

Thread.Sleep(100);
}
}

// コントロール毎Invokeします。
// フォームのコントロールが取得できない場合に有効です。
private void controlInvokeCounter() {
for (int i = 0; i <= 100; i++) {
textBox1.Invoke(new SetValue(delegate(int val) {
textBox1.Text = val.ToString();
}), i);
toolStripProgressBar1.ProgressBar.Invoke(new SetValue(delegate(int val) {
toolStripProgressBar1.Value = val;
}), i);
toolStripStatusLabel1.Owner.Invoke(new SetValue(delegate(int val) {
toolStripStatusLabel1.Text = val.ToString();
}), i);

Thread.Sleep(100);
}
}
}
}




ここでのポイントは、68行目の
toolStripStatusLabel1.Owner.Invoke(new SetValue(delegate(int val) {...

toolStripStatusLabelは、Invokeが取れないので、OwnerにてオーナーからInvokeを取得しています。
(toolStripProgressBarは、とれちゃいました(^_^;))


まとめると、
別スレッドからコントロールを操作したい場合は、コントロール、もしくは、
コントロールを持っているオーナーのInvokeを取得して操作する。



終わり。







テーマ : プログラミング
ジャンル : コンピュータ

[C#] Jsonライブラリの検討と設定ファイルの移行について

前回は、yamlのライブラリ検証で終っていしまいました。

今回は、jsonのライブラリ検証をしてみたいと思います。
調べた結果、以下の2つが有力のようです。
DynamicJson
JSON.NET


最後まで読むのが面倒だと思われるので、設定、状態保存をどのフォーマットにするかの検討結果を、
先に書きたいと思います。

[検討結果]
・yaml
 前回の結果から、yamlを使用するのであれば、現在(2011.11)であれば、
 YamlSerializer for .NETが有望だと思います。
 ただし、あまり機能は多くありません。
 ですので、現状ではyamlの対応は厳しいと個人的に思いました。

・json
 個人的には、Json.NETが有望だと思います。
 DinamicJsonは、.NET4.0のみの対応と考えると使用範囲が限定されます。
 Json.NETは、.NET2.0から対応していますし、作りこみが良く、
 機能も充実おり、ドキュメントも揃っています。
 両ライブラリとも非常に素晴らしいライブラリですので、どちらを使うにしても
 .NET環境でのJsonは卒なく使える印象を受けました。

・.NET環境での設定ファイルの移行について
 ここでは、.NET環境で設定、状態保存ファイルのフォーマットについて書きます。
 iniは、やはり配列等の状態を保存できないことから、時代遅れを感じます。
 xmlは、やはり見づらいというのが一番の回避理由でしょうか。
 また、ハンドリングも結構面倒くさいです。
 レジストリは、面倒くさいですし、ユーザによっては
 レジストリを弄って欲しくないということもあるので敬遠します。
 yamlに関しては、ライブラリが非充実ということがあります。
 Jsonは、ライブラリも充実しており、ハンドリングも楽です。
 
という理由から、これから設定、状態保存ファイルのフォーマットを検討するのであれば、Jsonをお薦めします。
ライセンスの問題もありますが、Json.NETはMITですし、DynamicJsonはMicrosoft Public Licenseです。
ですので、商用に使用しても問題無いです。
また、両ライブラリともソースコードを公開していますので、
変に上(小煩い上司や客先)が騒がなければ使用して全く問題ないと思います。
 

ということで、今回のJsonの2つについて検証した詳細を書きます。


[JSON]
・DynamicJson
このライブラリは、.NET Framework4.0が必須のようです。
なので、現状4.0を開発環境に入れることができない私の環境で検証することができませんでした。
(後日追記するかも??)
ただし、非常に軽く、使い勝手がよさそうです。
ドキュメントを見る限り、オリジナルクラスや配列等をjsonに落とすことが可能だと思います。
ただ、やはり4.0が必須っていうのは厳しいですね。

・JSON.NET
非常に使えます。
ライブラリも直感的に使用でき、快適ですし、機能も充実しています。
オリジナルクラス(リスト、配列込)を検証してみたいと思います。
オリジナルクラスのコード(Person.cs,Cat.cs,Car.cs)については、前回を参照ください。
以下のメインを実行するとこのようなJSONが出力されます。


{
    "Name":"智子",
    "Age":22,
    "IDs":[1,12],
    "Cats":[
        {
            "Age":1,
            "Name":"トラ"
        },
        {
            "Age":2,
            "Name":"たま"
        }
    ]
}




Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Newtonsoft.Json;


namespace JSONTest {
class Program {
// メイン
static void Main(string[] args) {
/*** オリジナルオブジェクト ***/
Person satoko = new Person("智子", 22);
satoko.Cats.Add(new Cat("トラ",1));
satoko.Cats.Add(new Cat("たま",2));
satoko.IDs = new List{1 , 12};


// Personシリアライズ - Console
string json = JsonConvert.SerializeObject(satoko, Formatting.Indented);
Console.WriteLine(json);
/* Console出力
{
"Name":"智子",
"Age":22,
"IDs":[1,12],
"Cats":[
{
"Age":1,
"Name":"トラ"
},
{
"Age":2,
"Name":"たま"
}
]
}
*/

// Personデシリアライズ - Console
Person desatoko = JsonConvert.DeserializeObject(json);


/*** コンストラクタに引数が必要な場合 ***/
Car vitz = new Car("123-456");
vitz.Name = "Vitz";

// Carシリアライズ - Console
json = JsonConvert.SerializeObject(vitz);
Console.WriteLine(json);
/* Console出力
{
"Number":"123-456",
"Name":"Vitz"
}
*/

// Carデシリアライズ - Console
Car devitz = JsonConvert.DeserializeObject(json);
}
}
}


Json.NETの他機能の備考として、
JsonReaderや、JsonWriterがありますが、
これらのオブジェクトは、行単位で処理するものです。
ですので、シリアライズで一発変換はできません。


という感じで、終わり。



テーマ : プログラミング
ジャンル : コンピュータ

[C#] yamlライブラリを検討してみました。

C#の設定ファイルの検討をしてみました。


C#でアプリケーションを設定する際に必ずといっていいほど設定ファイルが必要となってきます。

私が今まで経験した中で、Windowsアプリケーションでの設定ファイルは、
・iniファイル
・xmlファイル
・レジストリ
でした。

しかし、どれもしっくり来ません。
それは、以下の理由があります。

iniファイル
 メリット :
  ・伝統的な設定方法で、ライブラリやサンプルが充実している。
  ・Windowsを使っている人に説明しやすい。(よく使われているため)
  ・エディタ等で開いた際、見やすい。
 デメリット :
  ・配列などの階層化したデータの保存ができない
  ・クラスのシリアライズができない
  ・なんかダサい

xmlファイル
 メリット
  ・階層化データを表現できる。
  ・ライブラリが揃っている。
  ・クラスのシリアライズが可能である。
  ・Visual Studio等の[設定]にて簡易に作成できる(アプリケーション設定のみ)
 デメリット
  ・エディタ等で開いた際、編集がしづらい。(よく客先で怒られます。。。)

レジストリ
 メリット
  ・ユーザに勝手に変更が加えられない
  ・高速に読み込める
 デメリット
  ・エディタ等で変更ができない
  ・なんか色々大変で、客先でバグったときにテンパる。

このサイトに上記設定ファイルフォーマットの使い方等が載っています。

ということで、上記設定ファイルはいやだなぁーと思いつつ、、、。

そこで、RubyやPython等のLL言語では、標準となっているjsonやyamlをC#で動かせるライブラリを調べてみました。
一応ライブラリは存在するようですが、C#はLL言語と違い型の定義があります。
なので、疑心暗鬼になり、ちょっとした動作確認をしてみました。

[YAML]
Yaml Library for .NET
これは、非常に使えなかった。
以下に使えなかった点を上げます。
・yamlを書きこむ際、オブジェクトをシリアライズできないため、
 自分で作る必要がある。
・yamlを読み込む際、keyによるアクセスができない。
・作りこみが雑。

一応、設定ファイルを作るコードは作ってみましたが、
載せる必要も無いため、省略します。
オリジナルのコードも見てみましたが、酷過ぎる。時間の無駄でした。
こんなコードでYAML for.NETと名乗らないで欲しいです。

YamlSerializer for .NET
これは、使えます。
自分で作成したオブジェクトのシリアライズ、デシリアライズを簡単に行うことができます。
また、細かい配慮が感じられ、オリジナルクラスや、List等の配列もyaml化してくれます。
ライセンスMITなので、商用での使用も可能です。
(というか、作った人、日本人なんだ。。。)

使い方は、
ここから、dllを取得し、[参照設定]にて、dllの参照を追加するだけです。

以下に、コードを乗せておきます。
このコードは、コンソールアプリケーションです。
以下のコードを追加し、Mainを実行すると、

%YAML 1.2
---
!YamlTest.Person
IDs:
Capacity: 4
ICollection.Items: [1, 12]
Cats:
Capacity: 4
ICollection.Items:
- Age: 1
Name: トラ
- Age: 2
Name: たま
Age: 22
Name: 智子



のようなyamlを作ることができます。
ここでは、オリジナルクラスとして
Person <-- Cat
Car
のクラスを作っています。



Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Yaml;
using System.Yaml.Serialization;


namespace YamlTest {
class Program {
// メイン
static void Main(string[] args) {
string yamlpath = "person.yaml";
/*** オリジナルオブジェクト ***/
Person satoko = new Person("智子", 22);
satoko.Cats.Add(new Cat("トラ",1));
satoko.Cats.Add(new Cat("たま",2));
satoko.IDs = new List{1 , 12};

YamlSerializer ys;

// Personシリアライズ - Console
ys = new YamlSerializer();
string yaml = ys.Serialize(satoko);
Console.WriteLine(yaml);
// Personデシリアライズ - Console
ys = new YamlSerializer();
Person desatoko = (Person)ys.Deserialize(yaml)[0];

// Personシリアライズ - File
ys.SerializeToFile(yamlpath, satoko);
// Personデシリアライズ - File
ys = new YamlSerializer();
desatoko = (Person)ys.DeserializeFromFile(yamlpath)[0];


/*** コンストラクタに引数が必要な場合 ***/
Car vitz = new Car("123-456");
vitz.Name = "Vitz";

// Carシリアライズ - Console
ys = new YamlSerializer();
yaml = ys.Serialize(vitz);
Console.WriteLine(yaml);
/* Console 出力
%YAML 1.2
---
!YamlTest.Car
Number: 123-456
Name: Vitz
...
*/

// Carデシリアライズ - Console
YamlNode.DefaultConfig.AddActivator(
() => new Car(""));

Car devitz = (Car)ys.Deserialize(yaml)[0];

}
}
}




Person.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YamlTest {
public class Person {


private int _Age = 20;
private string _Name = "";

private List _IDs = new List();
private List _Cats = new List();


public string Name { get { return _Name; } set { _Name = value; } }

public int Age { get { return _Age; } set { _Age = value; } }

public List IDs { get { return _IDs; } set { _IDs = value; } }

public List Cats { get { return _Cats; } set { _Cats = value; } }

// Constractor
public Person(string name, int age) {
Name = name;
Age = age;
}

public Person() { }


public void sleep() {
System.Console.WriteLine("Person of " + Name + " is sleeping.");
}
public void eat(){
System.Console.WriteLine("Person of " + Name + " is eating.");
}
public void read() {
System.Console.WriteLine("Person of " + Name + " is sleeping.");
}
}
}



Cat.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YamlTest {
public class Cat {

private int _Age = 3;

private string _Name = "";

public int Age {
get {
return _Age;
}
set {
_Age = value;
}
}

public string Name {
get {
return _Name;
}

set {
_Name = value;
}
}


public Cat(string name , int age) {
Name = name;
Age = age;
}

public Cat() { }

public void sleep() {
System.Console.WriteLine("Cat is sleeping.");
}

public void eat() {
System.Console.WriteLine("Cat is eating.");
}

}
}




Car.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YamlTest {
public class Car {

private string _Number;

private string _Name;

public string Number { get { return _Number; } set { _Number = value; } }

public string Name { get { return _Name; } set { _Name = value; } }


// コンストラクタを与えます。
public Car(string number) { Number = number; }

}
}



yamlだけで疲れてしまったので、jsonはまた今度。。。

-- 追記 --
jsonライブラリについての検討と検討結果について書きました。
[C#] Jsonライブラリの検討と設定ファイルの移行について





テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

ss_9

名前 :ss_9
紹介 :
20代はエンジニア、30代はプロ、40代は管理、50代は人脈。

Twitterボタン

最新記事
カテゴリ
AD
月別アーカイブ
RSSリンクの表示
RSSリンクの表示
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。