code-prettify

2014年7月25日 星期五

C# StyleCop System using directives must be placed before all other using directives.

一般我們的專案會像這樣,使用了很多的 using 參考。
這時候我們就會使用 Visual Stdio 內建的功能,對 Using 進行整理。
右鍵 > 組合管理 Using > 移除和排序


移除和排序後的樣子,很方便對吧!

 但是呢?StyleCop 出來抱怨了,
「System using directives must be placed before all other using directives.」。
也就是說,所有 System 相關的 using 必須放在最前面。


從前面的圖片可以看的出來,SocketLibaray 比 System 的字母順序還前面,所以排在 System 的前面了。
這樣我們就不能用 Visual Stdio 內建的排序了嗎?只能手動調整了嗎?
放心,其實 Visual Stdio 是有這個設定的,在功能選單內,
選項 > 文字編輯器 > C# > 進階 > 組合管理 Using > 排序 Using 時先放置 'System' 指示詞
將這個選項打勾,然後按下確定。



接著再對剛剛的 using 做一次排序,
噹噹!依照我們希望的順序,System 在前面了喔!
這麼一來 StyleCop 也不會報錯了呢。

C# StyleCop 忽略特定錯誤訊息

雖然 StyleCop 蠻方便的,但是有時候難免會出現誤報,
像是這一行 IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
ipHostInfo 就被判定為匈牙利命名法 (Hungarian notation),
這時候只能換另一個變數命名,
或者,使用 Suppress 忽略掉這個錯誤訊息。

在這個函式上方加上這一行
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Reviewed.")]
就可以忽略掉這一個錯誤訊息。

至於每一次 StyleCop Rule 的 Suppress 要怎麼寫,
可以參考 StyleCop Rules Documentation ,
除了 Rule Suppressions 的說明之外,每個 Rule 最下方也有該 Rule 的Suppress 方法。
像是這次遇到的 SA1305 FieldNamesMustNotUseHungarianNotation 就是從這裡來的。

Reference
StyleCop
StyleCop Rules Documentation


C# 程式碼風格分析 StyleCop 與 Visual Studio Express 整合


首先到 http://stylecop.codeplex.com/ 網站下載並安裝 StyleCop,
安裝過程就下一步按到底就完成了。
如果你使用的 Visual Studio 不是 Express 版本 (Professional, Premium, Ultimate...etc),
這時候在 Visual Studio > 方案總管 裡面對著專案按下右鍵,就會出現 Run StyleCop,
詳細的說明請參考這篇文章  [Tool]程式碼風格分析-StyleCop

因為 Visual Studio Express 不支援任何 UI 方面的擴充功能 (Extensions),
所以就算安裝完之後,是不會有任何變化的。
這時候可以手動在專案檔 (.csproj) 上設定,讓每一次建置 (Build) 的時候都執行一次 StyleCop 檢查。

在專案檔裡面加上這一行:
<Import Project="$(ProgramFiles)\MSBuild\StyleCop\v4.7\StyleCop.targets" />

這麼一來,這個專案每次建置的時候,就會進行 StyleCop 檢查,錯誤訊息也會出現在 Visual Studio 的錯誤清單讓你檢視。當然,「檢示錯誤訊息」功能是不存在的,只能用錯誤代號自行查詢了。

延伸問題:
一、每個專案都要手動加上設定。
這點可以用靠修改範本讓新建立的專案都先加上設定,舊的就只能一個一個改。

二、如果這個專案在另一個沒有安裝 StyleCop 的電腦上建置,那專案就會建置失敗。
雖然可以透過 NuGet 安裝 StyleCop 來解決這個問題,但是考慮到 StyleCop Rule 的一致性,還是建議統一安裝 StyleCop。

Reference
StyleCop
Intergrating StyleCop with Visual Studio Express
[Tool]程式碼風格分析-StyleCop

2014年7月21日 星期一

C# Serialization

C# Serialzation

使用 C# 序列化物件

最近常遇到將物件序列化的問題,
想說乾脆將物件序列化的方法寫成一個工具,稱為 SerialzationHelper,
套上泛型就可以適用在所有的物件了。(當然該物件必須是 serializable 的才可以啦)

Book 是用來測試的可序列化類別,
Main 是使用序列化的過程,
SerialzationHelper 是序列化工具。

完整範例: Reference:
Basic Serialization
BinaryFormatter 類別
MemoryStream 類別
using Statement (C# Reference)

2014年5月7日 星期三

Write to file - Node.js

將文字新增在原本檔案之後,參考網路範例後改寫如下:

var fs = require('fs');

// 宣告函式
var writelog = function(filepath, log){
  fs.open(filepath, 'a', 666, function( e, id ) {
    fs.write(id, log, null, 'utf8', function(){
    fs.close(id, function(){
      //console.log('file closed');
    });
    });
  });
};

// 目錄要事先建好喔
var filepath = 'C:/Test/I-Love-You.txt'
var message = 'Hello Kitty!'

// 呼叫函式
writelog(filepath, message + '\r\n');


參考來源:
How to append to a file in Node?
http://stackoverflow.com/questions/3459476/how-to-append-to-a-file-in-node

2014年4月18日 星期五

Cocos2d-x 3.0 - Chapter 3 - How to Move a sprite

Cocos2d-x 3.0 - Chapter 3 - How to Move a sprite
Cocos2dxSimpleGame Series

在上一篇 Chapter 2 - How to Add a sprite 中,我們已經增加了一位英雄。但是英雄只有一個人太孤單了,所以我們來增加一些敵人。

addTarget() 這個函式會讓敵人隨機的出現,並從右向左移動。


void HelloWorld::addTarget()
{
 Sprite *target = Sprite::create("Target.png", Rect(0, 0, 27, 40));

 // Determine where to spawn the target along the Y axis
 Size winSize = Director::getInstance()->getWinSize();
 int minY = target->getContentSize().height / 2;
 int maxY = winSize.height - target->getContentSize().height / 2;
 int rangeY = maxY - minY;
 // srand( TimGetTicks() );
 int actualY = (rand() % rangeY) + minY;

 // Create the target slightly off-screen along the right edge,
 // and along a random position along the Y axis as calculated
 target->setPosition(Point(winSize.width + (target->getContentSize().width / 2), actualY));
 this->addChild(target);

 // Determine speed of the target
 int minDuration = (int)2.0;
 int maxDuration = (int)4.0;
 int rangeDuration = maxDuration - minDuration;
 // srand( TimGetTicks() );
 int actualDuration = (rand() % rangeDuration) + minDuration;

 // Create the actions
 FiniteTimeAction* actionMove =
  MoveTo::create((float)actualDuration,
  Point(0 - target->getContentSize().width / 2, actualY));

 FiniteTimeAction* actionMoveDone =
  CallFuncN::create(std::bind(&HelloWorld::spriteMoveFinished, this, std::placeholders::_1));

 target->runAction(Sequence::create(actionMove, actionMoveDone, NULL));
}

其中 CallFuncN::create(std::bind(&HelloWorld::spriteMoveFinished, this, std::placeholders::_1)) 使用了回呼函式,所以我們需要宣告 spriteMoveFinished 函式在 HelloWorld。


void HelloWorld::spriteMoveFinished(Node* sender)
{
 Sprite *sprite = (Sprite *)sender;
 this->removeChild(sprite, true);
}

接著,我們需要定時讓敵人出現在場景上,加入下列這段程式到 init 函中的 return 之前


this->schedule(schedule_selector(HelloWorld::gameLogic), 1.0);

然後實作 gameLogic() 函式


void HelloWorld::gameLogic(float dt)
{
 this->addTarget();
}

好了,所有的工作都完成了,建置然後看看結果吧:



參考資料:
Cocos2d-x
http://www.cocos2d-x.org/

Step by Step Cocos2dxSimpleGame Series (Old Version for cocos2d-x v2.x)
http://www.cocos2d-x.org/wiki/Step_by_Step_Cocos2dxSimpleGame_Series


Cocos2d-x 3.0 - Step by Step Cocos2dxSimpleGame Series

Cocos2d-x 3.0 - Step by Step Cocos2dxSimpleGame Series

將原先官方 wiki 上的 範例,從 Cocos2d-x 2.x 版本,改為 3.x 版本。
Souse : Step by Step Cocos2dxSimpleGame Series ( for cocos2d-x 2.x)

其中關於 Cocos2d-x 2.x to 3.0 的注意事項,請參考 Cocos2d-x 2.x to 3.0 rc1 Note 。

Chapter 1 - How to Create a New cocos2d-x project
Chapter 2 - How to Add a sprite
Chapter 3 - How to Move a sprite
Chapter 4 - How to Fire some Bullets
Chapter 5 - How to Detect the Collisions
Chapter 6 - How to Play Music and Sound Effect
Chapter 7 - Some Icing on the Cake