2006年04月26日

Interpreter ― 文法規則をクラスで表現する

   このエントリーをはてなブックマークに追加 Clip to Evernote
ここに掲載したコードは、『増補改訂版Java言語で学ぶデザインパターン入門 / 結城 浩(著)』に掲載されているサンプルコードをC#に移植したものです。移植後のコードの公開に関しては、結城氏の了解を得ています。
※当ソースは、Visual C# 2005 Express Editionで動作を確認しています。



ParseExceptionインターフェース
using System;

namespace Gushwell.DesignPatterns {
[Serializable]
public class ParseException : System.Exception {
public ParseException(string msg)
: base(msg) {
}
}
}

Nodeクラス
using System;

namespace Gushwell.DesignPatterns {
public abstract class Node {
public abstract void Parse(Context context);
}
}



ProgramNodeクラス
using System;

namespace Gushwell.DesignPatterns {
// <program> ::= program <command list>
public class ProgramNode : Node {
private Node commandListNode;

public override void Parse(Context context) {
context.SkipToken("program");
commandListNode = new CommandListNode();
commandListNode.Parse(context);
}

public override string ToString() {
return "[program " + commandListNode + "]";
}
}
}



CommandListNodeクラス
using System;
using System.Collections.Generic;

namespace Gushwell.DesignPatterns {
// <command list> ::= <command>* end
public class CommandListNode : Node {
private List<Node> list = new List<Node>();
public override void Parse(Context context) {
while ( true ) {
if ( context.CurrentToken() == null ) {
throw new ParseException("Missing 'end'");
} else if ( context.CurrentToken().Equals("end") ) {
context.SkipToken("end");
break;
} else {
Node commandNode = new CommandNode();
commandNode.Parse(context);
list.Add(commandNode);
}
}
}

public override string ToString() {
string s = "[";
for ( int i = 0; i < list.Count; i++ ) {
Node node = list[i];
s += node.ToString() + ( ( i == list.Count - 1 ) ? "" : "," );
}
return s + "]";
}
}
}



CommandNodeクラス
using System;

namespace Gushwell.DesignPatterns {
// <command> ::= <repeat command> | <primitive command>
public class CommandNode : Node {
private Node node;

public override void Parse(Context context) {
if ( context.CurrentToken().Equals("repeat") ) {
node = new RepeatCommandNode();
node.Parse(context);
} else {
node = new PrimitiveCommandNode();
node.Parse(context);
}
}

public override string ToString() {
return node.ToString();
}
}
}



<b>RepeatCommandNodeクラス</b>  
using System;

namespace Gushwell.DesignPatterns {
// <repeat command> ::= repeat <number> <command list>
public class RepeatCommandNode : Node {
private int number;
private Node commandListNode;

public override void Parse(Context context) {
context.SkipToken("repeat");
number = context.CurrentNumber();
context.NextToken();
commandListNode = new CommandListNode();
commandListNode.Parse(context);
}

public override string ToString() {
return "[repeat " + number + " " + commandListNode.ToString() + "]";
}
}
}



PrimitiveCommandNodeクラス
using System;

namespace Gushwell.DesignPatterns {
// <primitive command> ::= go | right | left
public class PrimitiveCommandNode : Node {
private string name;

public override void Parse(Context context) {
name = context.CurrentToken();
context.SkipToken(name);
if ( !name.Equals("go") && !name.Equals("right") &&
!name.Equals("left") ) {
throw new ParseException(name + " is undefined");
}
}

public override string ToString() {
return name;
}
}
}



StringTokenizerクラス
using System;
using System.Collections.Generic;
using System.Text;

namespace Gushwell.DesignPatterns {
class StringTokenizer {
private string[] strs;
private int index = -1;

public StringTokenizer(string text) {
this.strs = text.Split();
}
public string NextToken() {
return strs[++index];
}

public string CurrentToken() {
return strs[index];
}

public bool HasMoreTokens() {
return ( index + 1 ) < strs.Length;
}
}
}



Contextクラス
using System;

namespace Gushwell.DesignPatterns {
public class Context {
private StringTokenizer tokenizer;
private string currentToken;

public Context(string text) {
tokenizer = new StringTokenizer(text);
NextToken();
}

public virtual string NextToken() {
if ( tokenizer.HasMoreTokens() ) {
currentToken = tokenizer.NextToken();
} else {
currentToken = null;
}
return currentToken;
}

public virtual string CurrentToken() {
return currentToken;
}

public virtual void SkipToken(string token) {
if ( !token.Equals(currentToken) ) {
throw new ParseException("Warning: " + token +
" is expected, but " + currentToken + " is found.");
}
NextToken();
}

public virtual int CurrentNumber() {
int number = 0;
try {
number = System.Int32.Parse(currentToken);
} catch ( System.FormatException e ) {
throw new ParseException("Warning: " + e);
}
return number;
}
}
}



Programクラス
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Gushwell.DesignPatterns {
class Program {
static void Main(string[] args) {
try {
StreamReader reader =
new StreamReader("program.txt", System.Text.Encoding.Default);
System.String text;
while ( ( text = reader.ReadLine() ) != null ) {
Console.WriteLine("text = \"" + text + "\"");
Node node = new ProgramNode();
node.Parse(new Context(text));
Console.WriteLine("node = " + node);

}
Console.ReadLine();
} catch ( System.Exception ex ) {
Console.Error.WriteLine(ex.StackTrace);
}
}
}
}

  

Posted by gushwell at 21:31Comments(0)TrackBack(0)

2006年04月25日

TransactionScopeでの分散トランザクションへの昇格

   このエントリーをはてなブックマークに追加 Clip to Evernote
.NET Framework2.0 の ADO.NETでは、TransactionScope を使った場合、
自動的に、分散トランザクションに昇格するようだ。
ただ、単一のデータベースであるにも関わらず、

----
分散トランザクション マネージャ (MSDTC) のネットワーク アクセスは
無効になっています。 コンポーネント サービス管理ツールを使用して、
MSDTC のセキュリティ構成でネットワーク アクセスの DTC を有効にして
ください。
----

という例外が発生してしまう。
DBはそれほど詳しくないので、何か大きな見落としが
あるのかな。それとも大きな勘違いをしているのか。。。
  
Posted by gushwell at 22:56Comments(2)TrackBack(0)

2006年04月22日

Japan MVP Summit 2006

   このエントリーをはてなブックマークに追加 Clip to Evernote
4/22 Japan MVP Summit 2006に参加しました。
その中で、一番興味を引いたのが、Expressionについてです。「Microsoft Expression」+Visual Studio の組み合わせによる開発はとても興味があります。
Community Technology Preview (CTP)版がダウンロードできるので、時間があったら、動かしてみようと思います。

  
Posted by gushwell at 23:05Comments(0)TrackBack(0)

2006年04月19日

Command ― 命令をクラスにする

   このエントリーをはてなブックマークに追加 Clip to Evernote
ここに掲載したコードは、『増補改訂版Java言語で学ぶデザインパターン入門 / 結城 浩(著)』に掲載されているサンプルコードをC#に移植したものです。移植後のコードの公開に関しては、結城氏の了解を得ています。
※当ソースは、Visual C# 2005 Express Editionで動作を確認しています。



ICommandインターフェース
using System;

namespace Gushwell.DesignPatterns.Command {

public interface ICommand {
void Execute();
}
}


DrawCommandクラス
using System;
using System.Drawing;
using Gushwell.DesignPatterns.Command;

namespace Gushwell.DesignPatterns.Drawer {

public class DrawCommand : ICommand {
// 描画対象
protected internal IDrawable drawable;

// 描画位置
private System.Drawing.Point position;

// コンストラクタ
public DrawCommand(IDrawable drawable, Point position) {
this.drawable = drawable;
this.position = position;
}

// 実行
public virtual void Execute() {
drawable.Draw(position.X, position.Y);
}
}
}


MacroCommandクラス
using System;
using System.Collections;

namespace Gushwell.DesignPatterns.Command {

public class MacroCommand : ICommand {
// 命令の集合
private Stack commands = new Stack();

// 実行
public virtual void Execute() {
foreach (ICommand cmd in commands) {
cmd.Execute();
}
}

// 追加
public virtual void Append(ICommand cmd) {
if (cmd != this) {
commands.Push(cmd);
}
}

// 最後の命令を削除
public virtual void Undo() {
if (!(commands.Count == 0)) {
commands.Pop();
}
}

// 全部削除
public virtual void Clear() {
commands.Clear();
}
}
}



IDrawableインターフェース
using System;

namespace Gushwell.DesignPatterns.Drawer {

public interface IDrawable {
void Draw(int x, int y);
}
}



DrawCanvasクラス
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Gushwell.DesignPatterns.Command;

namespace Gushwell.DesignPatterns.Drawer {
public partial class DrawCanvas : UserControl, IDrawable {
public DrawCanvas() {
InitializeComponent();
}
// 描画色
private Color color = Color.Red;
// 描画する点の半径
private int radius = 6;
// 履歴
private MacroCommand history = null;

public void Draw(int x, int y) {
using ( Graphics g = CreateGraphics() )
using ( Brush brush = new SolidBrush(color) ) {
g.FillEllipse(brush, x - radius, y - radius, radius * 2, radius * 2);
}
}
public void SetHistory(MacroCommand history) {
this.history = history;
}

private void DrawCanvas_Paint(object sender, PaintEventArgs e) {
if (history != null)
history.Execute();
}
}
}



DrawCanvasクラス (IDEが作成したソース : DrawCanvas.Designer.cs)
namespace Gushwell.DesignPatterns.Drawer {
partial class DrawCanvas {
private System.ComponentModel.IContainer components = null;

protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}

#region コンポーネント デザイナで生成されたコード

/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent() {
this.SuspendLayout();
//
// DrawCanvas
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "DrawCanvas";
this.Paint +=
new System.Windows.Forms.PaintEventHandler(this.DrawCanvas_Paint);
this.ResumeLayout(false);

}

#endregion
}
}



Form1クラス
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Gushwell.DesignPatterns.Command;
using Gushwell.DesignPatterns.Drawer;

namespace Gushwell.DesignPatterns {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
drawCanvas1.SetHistory(history);
}

private void Form1_MouseDown(object sender, MouseEventArgs e) {
//userControl11.draw(e.X, e.Y);
}
private MacroCommand history = new MacroCommand();

private bool drag = false;
private void drawCanvas1_MouseDown(object sender, MouseEventArgs e) {
drag = true;

}

private void drawCanvas1_MouseMove(object sender, MouseEventArgs e) {
if (drag) {
ICommand cmd = new DrawCommand(drawCanvas1, e.Location);
history.Append(cmd);
cmd.Execute();
}
}

private void drawCanvas1_MouseUp(object sender, MouseEventArgs e) {
drag = false;
}

private void clearButton_Click(object sender, EventArgs e) {
history.Clear();
drawCanvas1.Invalidate();
}
}
}



Form1クラス (IDEが作成したソース : Form1.Designer.cs)
using Gushwell.DesignPatterns.Drawer;

namespace Gushwell.DesignPatterns {
partial class Form1 {
private System.ComponentModel.IContainer components = null;

protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows フォーム デザイナで生成されたコード

private void InitializeComponent() {
this.clearButton = new System.Windows.Forms.Button();
this.drawCanvas1 = new Gushwell.DesignPatterns.Drawer.DrawCanvas();
this.SuspendLayout();
//
// clearButton
//
this.clearButton.Location = new System.Drawing.Point(104, 3);
this.clearButton.Name = "clearButton";
this.clearButton.Size = new System.Drawing.Size(75, 23);
this.clearButton.TabIndex = 1;
this.clearButton.Text = "Clear";
this.clearButton.UseVisualStyleBackColor = true;
this.clearButton.Click += new System.EventHandler(this.clearButton_Click);
//
// drawCanvas1
//
this.drawCanvas1.BackColor = System.Drawing.SystemColors.Window;
this.drawCanvas1.Location = new System.Drawing.Point(1, 32);
this.drawCanvas1.Name = "drawCanvas1";
this.drawCanvas1.Size = new System.Drawing.Size(290, 239);
this.drawCanvas1.TabIndex = 0;
this.drawCanvas1.MouseDown +=
new System.Windows.Forms.MouseEventHandler(this.drawCanvas1_MouseDown);
this.drawCanvas1.MouseMove +=
new System.Windows.Forms.MouseEventHandler(this.drawCanvas1_MouseMove);
this.drawCanvas1.MouseUp +=
new System.Windows.Forms.MouseEventHandler(this.drawCanvas1_MouseUp);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.clearButton);
this.Controls.Add(this.drawCanvas1);
this.Name = "Form1";
this.Text = "Command Pattern Sample";
this.MouseDown +=
new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown);
this.ResumeLayout(false);

}

#endregion

private DrawCanvas drawCanvas1;
private System.Windows.Forms.Button clearButton;
}
}


Programクラス
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace Gushwell.DesignPatterns {
static class Program {
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

  
Posted by gushwell at 21:58Comments(0)TrackBack(0)

2006年04月16日

NEXT WISE

   このエントリーをはてなブックマークに追加 Clip to Evernote
家に『NEXT WISE』が届きました。『NEXT WISE』は、IT業界特化型フリーペーパーで、Webページで定期購読を申し込むと、無料で送付してくれます。
凄いですね。就職情報やお店紹介的なフリーペーパーは沢山ありますが、なんと、IT業界の話題を扱った雑誌が無料というのは、ちょっと驚きです。
「25〜35歳の若く、バイタリティ溢れるビジネスパーソンをメインターゲットに据えて」いるということで、僕はターゲットからはずれているようですが(笑)、ちゃんと自宅に送付してくれました。地方にいる人にとってはうれしいサービスです。
  
Posted by gushwell at 23:41Comments(1)TrackBack(0)

2006年04月14日

MFC

   このエントリーをはてなブックマークに追加 Clip to Evernote
手元にある .NET Framework SDK ドキュメントには、「MFCリファレンス」というタイトルで、.NET Framework のリファレンスが載っている。
いつから、、.NET Framework に対し、MFC という言葉を使い出したのだろう。  
Posted by gushwell at 20:43Comments(0)TrackBack(0)

Proxy ― 必要になってから作る

   このエントリーをはてなブックマークに追加 Clip to Evernote
ここに掲載したコードは、『増補改訂版Java言語で学ぶデザインパターン入門 / 結城 浩(著)』に掲載されているサンプルコードをC#に移植したものです。移植後のコードの公開に関しては、結城氏の了解を得ています。
※当ソースは、Visual C# 2005 Express Editionで動作を確認しています。



IPrintableインターフェース
using System;

namespace Gushwell.DesignPatterns {
public interface IPrintable {
void SetPrinterName(string name); // 名前の設定
string GetPrinterName(); // 名前の取得
void Print(string string_Renamed); // 文字列表示(プリントアウト)
}
}



Printerクラス
using System;

namespace Gushwell.DesignPatterns {
public class Printer : IPrintable {
private string name;

// コンストラクタ
public Printer() {
HeavyJob("Printerのインスタンスを生成中");
}

// コンストラクタ
public Printer(string name) {
this.name = name;
HeavyJob("Printerのインスタンス(" + name + ")を生成中");
}

// 名前の設定
public virtual void SetPrinterName(string name) {
this.name = name;
}

// 名前の取得
public virtual string GetPrinterName() {
return name;
}

// 名前付きで表示
public virtual void Print(string string_Renamed) {
Console.WriteLine("=== " + name + " ===");
Console.WriteLine(string_Renamed);
}

// 重い作業(のつもり)
private void HeavyJob(string msg) {
Console.Write(msg);
for (int i = 0; i < 5; i++) {
System.Threading.Thread.Sleep(1000);
Console.Write(".");
}
Console.WriteLine("完了。");
}
}
}



PrinterProxyクラス
using System;

namespace Gushwell.DesignPatterns {
public class PrinterProxy : IPrintable {
private string name; // 名前
private Printer real; // 「本人」

public PrinterProxy() {
}

// コンストラクタ
public PrinterProxy(string name) {
this.name = name;
}

// 名前の設定
public virtual void SetPrinterName(string name) {
lock (this) {
if (real != null) {
real.SetPrinterName(name); // 「本人」にも設定する
}
this.name = name;
}
}

// 名前の取得
public virtual string GetPrinterName() {
return name;
}

// 表示
public virtual void Print(string string_Renamed) {
Realize();
real.Print(string_Renamed);
}

// 「本人」を生成
private void Realize() {
lock (this) {
if (real == null) {
real = new Printer(name);
}
}
}
}
}



Programクラス
using System;

namespace Gushwell.DesignPatterns {
public class Program {

[STAThread]
public static void Main(string[] args) {
IPrintable p = new PrinterProxy("Alice");
Console.WriteLine("名前は現在" + p.GetPrinterName() + "です。");
p.SetPrinterName("Bob");
Console.WriteLine("名前は現在" + p.GetPrinterName() + "です。");
p.Print("Hello, world.");
}
}
}

  
Posted by gushwell at 20:17Comments(0)TrackBack(0)

2006年04月12日

あなたも MSMVPになれる!

   このエントリーをはてなブックマークに追加 Clip to Evernote
MVP の可能性を持った方々が自らの活動をアピールし、MVP に立候補するためのMVP 審査応募ページが、新設されました。

  
Posted by gushwell at 00:05Comments(0)TrackBack(0)