Visual Studio BuildEvents Macros

Name Value
OutDir ..\bin\Debug\ (Build output path)
ConfigurationName Debug
ProjectName GBLib.App
TargetName GBLib.App
TargetPath O:\Data\MyProjects\GBLib\bin\Debug\GBLib.App.Exe
ProjectPath O:\Data\MyProjects\GBLib\GBLib.App\GBLib.App.csproj
ProjectFileName GBLib.App.csproj
TargetExt .exe
TargetFileName GBLib.App.Exe
DevEnvDir C:\Program Files\Microsoft Visual Studio 11.0\Common7\IDE
TargetDir O:\Data\MyProjects\GBLib\bin\Debug\
ProjectDir O:\Data\MyProjects\GBLib\GBLib.App\
SolutionFileName Minimal-GBLib.sln
SolutionPath O:\Data\MyProjects\GBLib\Minimal-GBLib.sln
SolutionDir O:\Data\MyProjects\GBLib\
SolutionName Minimal-GBLib
PlatformName x86
ProjectExt .csproj
SolutionExt .sln
   
0 コメント

Windows Service App

To Create a Windows Service App,

1.Start Visual C# (Express)

2.Create New Project (Empty Project) + Add Reference (System.ServiceProcess, System.Configuration, System.Configuration.Install)

3.Create a Service Class

続きを読む 3 コメント

C# indexed property

Unlike VB.net C# does not support a property with index.
VB.net you can define a property like

Public Property Hoge(Index as Integer) as String
    Get
        Return mHoge(Index)
    End Get
    Set
        mHoge(Index) = Value
    End Set
End Property

But you can do something like

public class IndexableProperty<T>
{
    private T[] mData;
    public IndexableProperty(T[] data){
        this.mData = data;
    }
    public T this[int index] {
        get
        {
            return mData[index];
        }
        set
        {
            mData[index] = value;
        }
    }
}

Then use this class for the property you want to have an index.

public class HogeHoge
{
    private string[] myData;
    private IndexableProperty<string> mHoge;
    public IndexableProperty<string> Hoge
    {
        get {
            if (mHoge == null){
                mHoge = new IndexableProperty(myData);
            }
            return mHoge;
        }
    }
}

SharpDevelop

最近SharpDevelopに心が傾いた。

いつもVisual C#2010 Expressで頑張っていたけど、本職の方でUltimate使ってると、やっぱり色々不便さを感じていた。

具体的には、テスト(NUnit)が統合されていなかったり、言語が違うプロジェクトをソリューションに追加できなかったり・・。

で、ちょっとSharpDevelopを使ってみたら、なんとまぁ、そこらへんがうまくいくじゃないですか!!

というわけで、ここしばらく作っていたプログラムをSharpDevelopで開いてみた。

そして、Webプロジェクトなんかも追加して「いい感じ~~~」と思っていた。

今日、ちょっとEF4のモデルから生成(t4 generator)しているSQLスクリプトを変更が必要になった。

で、スクリプトを変更して保存!したら「EF.Utility.CS.ttincludeがないって怒られた」。

そりゃそうかも、"EF.Utility.CS.ttinclude"はもともとVisualStudioのIDEExtentionだもの。

まだVisualStudioも削除していなかったので、なんとかファイルを探してフルパスでincludeしたら・・・・

System.Data.Entity.dllが読めないだの、なんだの・・・。

 

やめました。

時間を掛けたくなかったのでやめました。

 

でも、SharpDevelop自体は使いやすいと思う。プロジェクトによってはそっちでもいいかな。

ていうか、DAL周りだけVisualStudioにしておいて、あとはSharpDevelopにしてもいいかも・・。

 

0 コメント

TextBox AutoComplete

I made a form with a textbox.

This textbox is for country name and I wanted to help input with AutoComplete.

 

So I coded.

foreach (M_Country country in M_CountryList)
{
    txtCountry.AutoCompleteCustomSource.Add(country.Name);
}

 

But it was very slow.

 

First I thought M_CountryList (which is VisiCoolStorage List object) was not fetching the data properly and seeking data slowly.

But then it appeard that reading data isn't slow at all!

The problem was adding items to the customSource.

Although the control is not displayed yet, somehow it takes quite a long time to add many items into it.

 

Solution:

AutoCompleteStringCollection sc = new AutoCompleteStringCollection();
foreach (M_Country country in Program.M_CountryList)
{
    sc.Add(country.Name);
}
txtCountry.AutoCompleteCustomSource = sc;

 

Creating a non-visible collection to add items and then assign the collection to AutoCompleteCustomSource.

Simple and fast.

 

Good!!!

0 コメント

Vici Coolstorage + Genericはすごいぞ!

C#+asp.netでアプリケーションを作ろうと思う。

で、今回フレームワークとしてVici MVCを見つけた。けっこう使いやすそう。

 

http://viciproject.com/

 

そして、DBアクセスにはvici coolstorageを使おう!

これまた、結構使いやすそう。

 

ところが、ちょっと壁にぶつかった。

というのも、データベースにはすでにデータが有る。というか初期状態のデータがすでにある。

そして、主キーはPrimaryと指定してあるが、前に作っていたプログラムでは新規レコード追加時にコードで次のキー値をセットしていた。

そして、そのキー値が別のリレーションを貼ったテーブルにも使われていた。

つまり、このフィールドは自動的にインクリメントしたいけど、いま入っている値はそのまま利用したい。

 

単純にコーディングすると、モデルクラスのイベント処理で対応できるらしい。

http://vici.stackexchange.com/questions/94/custom-primary-key-in-coolstorage

 

ところが、モデルがいっぱいあって、全部のクラスに同じコードを書くのが面倒だし、バグの元になる。

訂正が必要になったときに見落とす可能性が増えるからね。

 

いろいろ調べながらクラスを作ってみた。

やっぱりGenericはすごいね。今日もまた感動した。

 

まず、すべてのテーブルはIDという整数値のフィールドがあって、そこが主キーになっている。

なので、それをインターフェイスとして宣言する。

 

    public interface M_IDTable
    {
        int ID { get; set; }
    }

 

よし。

 

次にGenericを利用してIDフィールドの最大値+1を取ってくるメソッドを作ろう。

    public class MaxIdentifierUtil
    {
        public static int GetNext<T>() where T : CSObject<T, int>
        {
            int? MaxId = (int?)CSObject<T>.GetScalar("ID", CSAggregate.Max);
            if (MaxId == null)
            {
                return 1;
            }
            return (int)MaxId + 1;
        }

        public static void SetNextMaxID<T>(T sender, EventArgs e) where T : CSObject<T, int>, M_IDTable
        {
            sender.ID = MaxIdentifierUtil.GetNext<T>();
        }
    }

 

次に、モデルクラス。これはCSObjectを継承しなければいけない。さらに、今回作ったM_IDTableインターフェイスも実装する。

で、追加イベントで上記クラスのSetNextMaxIDメソッドを呼び出すようにする。


    [MapTo("M_UserLevel")]
    public abstract partial class M_UserLevel : CSObject<M_UserLevel, int>, M_IDTable
    {
        static M_UserLevel(){

            AnyObjectCreating += MaxIdentifierUtil.SetNextMaxID<M_UserLevel>;

        }

        public abstract int ID { get; set; }     //  Primery Key
        public abstract string Name { get;set;}
    }

 

 

動いた!!

 

ありがとうGeneric!

0 コメント

C# Loop within enum values.

I sometime want to loop within enum values.

For instance,

public enum {

     me = 100,

     you = 2000,

     he = 300

}

 

You can use Enum class to make it.

 

foreach (int loopValue in Enum.GetValues(typeof(enum))) {

    System.Console.WriteLine("Current Value is {0}",loopValue);

}

 

Cool!

C# Unit Testing

English today....

 

I have recently started using NUnit testing framework.

It is just lovely! I am not too familiar with "Test First" but I love this.

 

Here are some tips to start with.

 

1.Download NUnit (Of course!)

http://www.nunit.org/

 

2.Install it. (of course...isn't it??)

 

3.Create an external tool entry

  Menu [Tools] - [External Tools...]

  Then entry as below.

     Title : NUnit (Too obvious??)

     Command : C:\Program Files\NUnit 2.5.4\bin\net-2.0\nunit.exe (you may need to midify this accordingly to your configuration.

     Arguments : /run $(ProjectDir)/$(ProjectFileName)

     (with /run option, it will start testing automatically. Here you can also specify which build to test, default is "debug" but if you give an option "/config:Release", then it will start testing with release build.)

 

4.Additional option to the project

 you can set VS to start the test whenever you build the project.

"C:\Program Files\NUnit 2.5.4\bin\net-2.0\nunit-console.exe" "$(TargetPath)"

 

 

C#でEnumをタイプセーフに・・・

C#のEnumはとっても便利。


でも、通信プログラムなんかでは、列挙値と数値や文字列との相互変換が必要だったりする。
System.Enum のParse関数はそれを上手くやってくれるんだけど、ちょっと不満。


たとえば、

public enum Gender {
Male = 1,
Female = 2
};


という列挙を宣言したとき。

Gender X = (Gender)Enum.Parse(typeof(Gender),"9")


なんてコードが実行時にもエラーにならないんです!
キャストしまくってるのでコンパイル時にエラーが補足できないのはしょうがないとしても、実行時には列挙されていない値は・・・なんとかしろよぉ!
ということで、以下の関数をつくりました。

public class EnumUtility<T>
{
public static T GetEnumObject(string value)
{
if (!typeof( T).IsEnum)
throw new ArgumentException("T Must be an Enum");

int intvalue; //TryParse用のダミー

if (!int.TryParse(value,out intvalue))
throw new ArgumentException("Value must be a numeric value");

T result = ( T)Enum.Parse( typeof( T), value);

if (int.TryParse(result.ToString(), out intvalue))
throw new ArgumentException("Enum Value not found");

return result;
}
}


使い方は、 EnumUtility<Gender>.GetEnumObject("9")のように呼び出すだけです。

このとき引数で渡された文字列が列挙値に存在しない場合、ArgumentExceptionがThrowされます。

 

いかがでしょう?

 

 

修正:2010/06/16 クラスの宣言文がなかったのでソースが不完全でした。

また、使い方も書いていなかったので、自分で見直したときに使い方を忘れていました・・・。だめじゃん。