npm の 使い方

npm の基本的な使い方をまとめておきます。

目次

プロジェクト の 初期化

現在のディレクトリをルートディレクトリとして package.json を作成します。 package.json には今から作ろうとしているプロジェクトで利用するパッケージ情報 (以下の インストール を行った情報) が記載されます。

基本的には質問に答えて入力していくだけで package.json が初期化されます。 もし、すでに package.json が存在している場合、記載されているパッケージ情報に従って必要なパッケージをダウンロードおよび配置設定します。

npm init

package.json に依存関係を保存する場合、インストール時に --save オプションを付与して保存します。

パッケージ の インストール

パッケージ名 %PACKAGE_NAME% を指定して現在のプロジェクトにパッケージをインストールします。 --save オプションを付けると、 package.json に依存関係情報を書き込みます。

npm install %PACKAGE_NAME%
npm install %PACKAGE_NAME% --global

ローカルインストール と グローバルインストール

パッケージインストール先は 「ローカル」 と 「グローバル」 の2種類があります。 --global または -g オプションを付けるかどうかでローカルインストールとグローバルインストールを切り替えられます。 それぞれの違いは以下の通りです。

ローカルインストール (--global オプションなし)

  • 現在のプロジェクトの依存関係として取り込む ( Node.js の require で使う) 場合はローカルインストールします
  • インストール先は現在のプロジェクト配下に作られる node_modules フォルダ配下にインストールされます
  • コマンドとして実行する場合はパスを通して実行する必要があります

グローバルインストール (--global オプションあり)

  • コマンドラインツール (e.g. bower, grunt, jshint) はグローバルインストールします
  • インストール先はデフォルトなら以下の場所
    C:\Users\<UserName>\AppData\Roaming\npm\node_modules
  • パスが通っているので実行はコマンドをそのまま叩けば実行できる

パッケージ の アンインストール

インストール済みのパッケージを削除します。

npm uninstall %PACKAGE_NAME%

インストール済み パッケージ の 一覧表示

インストールされているパッケージの一覧を表示します。

npm ls

パッケージ の 更新

インストールされているパッケージに新しいバージョンがあれば更新を行います。

npm update %PACKAGE_NAME%

よく使うコマンドに絞ってまとめてみました。 とりあえずここに記載のコマンドが理解できていれば何とかはなるかと思います。

log4net の 使い方

少し今更なのですが…忘れてしまっていて調べなおしを行ったのでメモしておきます。

log4net の 基本的な利用方法を手順に従ってまとめてみました。 とりあえず利用するには以下の手順に従ってコピペしていけば利用できるはずです。

概要

  1. log4net を プロジェクト に組み込
  2. AssemblyInfo.cs へ追記
  3. log4net.config の作成
  4. ログ出力の実装

1. log4net を プロジェクト に組み込み

以前はアセンブリをダウンロードしてきて参照設定して…とありましたが、 現在は NuGet から取得可能です。

  1. プロジェクトを右クリック、「NuGetパッケージの管理」を選択

  2. 検索窓に「log4net」を入力

  3. 検索結果の log4net の「インストール」を選択

  4. ソリューションエクスプローラーで参照設定に「log4net」があることを確認

2. AssemblyInfo.cs へ追記

log4net の設定ファイルがどこにあるかを記載します。 ここでは log4net.config というファイル名にしてあります。 また、 Watch を指定することで、設定ファイルに変更があった場合に動的に読み込みを行ってくれるようになります。

AssemblyInfo.cs

// log4net configuration file
[assembly: log4net.Config.XmlConfigurator(ConfigFile=@"log4net.config", Watch=true)]

3. log4net.config の作成

プロジェクトルートに log4net.config ファイルを追加します。 追加した log4net.config はリリース時にコピーされる必要があるので、「出力ディレクトリにコピー」を「常にコピー」に設定しておきます。

以下では追加した log4net.config に log4net の設定を定義します。 サンプルなので一定サイズごとにファイル分割を行うログ出力を行える設定にしてあります。

log4net.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <log4net>

    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="application.log" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="10" />
      <maximumFileSize value="1MB" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%d{yyyy-MM-ddTHH:mm:ss} [%-5level] - %message%newline" />
      </layout>
    </appender>

    <root>
      <level value="ERROR" />
      <appender-ref ref="RollingLogFileAppender" />
    </root>

  </log4net>
</configuration>

4. ログ出力の実装

ログ出力は LogManager.GetLogger()ILog を取得して利用します。

    public static void Main(params string args)
    {
        // ロガーの取得
        // (補足)log4net.config の appender@name に
        //       引数で渡した名前の appender は存在しないので root が取得される
        var logger = LogManager.GetLogger(Assembly.GetExecutingAssembly().FullName);

        // ログ出力
        logger.Debug("デバッグ:処理の中間情報");
        logger.Info("情報:操作履歴");
        logger.Warn("注意:現在は正常に動作が続けられるがデータ不整合の可能性がある操作。");
        logger.Error("エラー:復旧可能な障害。継続できるが処理はロールバックされる。");
        logger.Fatal("障害:アプリケーションが強制終了する障害");
    }

簡単にですが…メモ程度に log4net の使い方をまとめておきました。 これでまた調べることは無くなるはず!

C# で string と MemoryStream を 変換 する 方法

Web通信やファイル操作を行う際、文字列(String) と メモリ配列(MemoryStream) を交換が発生します。 今回はそれぞれを相互へんかんする方法をまとめました。

まぁ、実際には「まとめ」に記載しているサンプルコードをコピペして利用すればラクだと思います。

目次

String → MemoryStream 変換

using System.IO;
using System.Text;

class Class1
{
    public MemoryStream GetMemoryStream(string text)
    {
        return new MemoryStream(Encoding.UTF8.GetBytes(text));
    }
}

MemoryStream → String 変換

using System.IO;
using System.Text;

class Class1
{
    public string GetString(MemoryStream stream)
    {
        return Encoding.UTF8.GetString(stream.ToArray());
    }
}

まとめ

文字列⇔メモリストリームの相互変換は拡張メソッドに定義しました。 以下のファイルをプロジェクトに組み込めば簡単に相互変換を利用できます。

メモリストリーム→文字列の変換メソッド名が ToString でデフォルトと被っている点がいまいちですが… いい名前が思いつかずこのままにしています。 利用する際は Encoding の指定をお忘れなく…。

ConverterExtensions.cs

using System.IO;
using System.Text;

namespace Sample
{
    /// <summary>
    /// 文字列とメモリストリームの相互変換拡張メソッドを提供します。
    /// </summary>
    public static class ConverterExtensions
    {
        /// <summary>
        /// 文字エンコーディングを指定して現在の文字列を表すメモリストリームを取得します。
        /// </summary>
        /// <param name="text">現在の文字列</param>
        /// <param name="encoding">文字エンコーディング</param>
        /// <returns>メモリストリーム</returns>
        public static MemoryStream ToMemoryStream(this string text, Encoding encoding)
        {
            return new MemoryStream(encoding.GetBytes(text));
        }

        /// <summary>
        /// 文字エンコーディングを指定して現在のメモリストリームを表す文字列を取得します。
        /// </summary>
        /// <param name="stream">メモリストリーム</param>
        /// <param name="encoding">文字エンコーディング</param>
        /// <returns>文字列</returns>
        public static string ToString(this MemoryStream stream, Encoding encoding)
        {
            return encoding.GetString(stream.ToArray());
        }
    }
}

使い方

using Sample;

public class Class1
{
    public void ConvertFromStringToMemoryStream()
    {
        var stream = new MemoryStream();
        var text = stream.ToString(Encoding.UTF8);
    }

    public void ConvertFromMemoryStreamToString()
    {
        var text = "なにか文字列";
        text.ToMemoryStream(Encoding.UTF8);
    }
}

C# の DataGridView で ソート を 無効化 する 方法

DataGridView ネタ が続いています。。 今回は DataGridView で ソート を 無効化する 方法。 といっても方法は簡単で、 DataGridView の カラム に対して NotSortable を設定するだけです。 具体的な方法は以下で見ていきます。


目次


デザイナ で 設定する

以下では Visual Studio の デザイナから修正を行います。 デザイナから修正するとコードが隠れるので、ソート無効化したいカラムが確定しているならこの方法が良いと思います。

  1. ソート無効化したい DataGridView のタスクを開きます。

  2. 「列の編集」を選択します。

  3. ソート無効化したいカラムの SortModeNotSortable にします。

コード で 設定する

行うことは上記のGUI設定と同じです。 動的に変更したいという要望がない限り、GUIで設定した方がコードが隠れて良い気がします。

以下のサンプルコードではすべてのカラムでソートを無効化しています。

public partial class Form1 : Form
{
    public Form1()
    {
        this.InitializeComponent();

        // dataGridView1 の すべてのカラムで ソート を 無効化
        foreach (DataGridViewColumn column in this.dataGridView1.Columns)
        {
            column.SortMode = DataGridViewColumnSortMode.NotSortable;
        }
    }
}

これまにで DataGridView をいくつか記事にしてきましたが、とりあえず今回まででひと段落です。 これまでの記事と組み合わせれば DataGridView はきっとうまく使いこなせるようになっているハズ!

C# の DataGridView で カスタムデータ を ソート可能 にする方法

前回の記事 では、カスタムデータを利用して DataGridView を表示する方法をまとめましたが、 今回はその続きで DataGridView で カスタムデータ を ソート可能にする 方法 を見ていきます。


目次


概要

DataGridView で ソート可能 にすることは簡単で、 以下に載せる SortableBindingList を DataGridView.DataSource へ設定するだけです。

なんのひねりもないのでサクッとサンプルコードを見ていきましょう。

ソート可能なバインディングリスト

何と言ってもこのソースコードが必要! これさえあればカスタムデータも DataGridView でソートできる! そんな魔法のようなリストオブジェクトのサンプルコードを以下に載せます。

SortableBindingList.cs

namespace Sample
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    /// <summary>
    /// ソート可能なバインディングリストクラス
    /// </summary>
    /// <typeparam name="T">リスト内容</typeparam>
    public class SortableBindingList<T> : BindingList<T>
        where T : class
    {
        /// <summary>
        /// ソート済みかどうか
        /// </summary>
        private bool isSorted;

        /// <summary>
        /// 並べ替え操作の方向
        /// </summary>
        private ListSortDirection sortDirection = ListSortDirection.Ascending;

        /// <summary>
        /// ソートを行う抽象化プロパティ
        /// </summary>
        private PropertyDescriptor sortProperty;

        /// <summary>
        /// SortableBindingList クラス の 新しいインスタンス を初期化します。
        /// </summary>
        public SortableBindingList()
        {
        }

        /// <summary>
        /// 指定した リストクラス を利用して SortableBindingList クラス の 新しいインスタンス を初期化します。
        /// </summary>
        /// <param name="list">SortableBindingList に格納される System.Collection.Generic.IList</param>
        public SortableBindingList(IList<T> list)
            : base(list)
        {
        }

        /// <summary>
        /// リストがソートをサポートしているかどうかを示す値を取得します。
        /// </summary>
        protected override bool SupportsSortingCore
        {
            get { return true; }
        }

        /// <summary>
        /// リストがソートされたかどうかを示す値を取得します。
        /// </summary>
        protected override bool IsSortedCore
        {
            get { return this.isSorted; }
        }

        /// <summary>
        /// ソートされたリストの並べ替え操作の方向を取得します。
        /// </summary>
        protected override ListSortDirection SortDirectionCore
        {
            get { return this.sortDirection; }
        }

        /// <summary>
        /// ソートに利用する抽象化プロパティを取得します。
        /// </summary>
        protected override PropertyDescriptor SortPropertyCore
        {
            get { return this.sortProperty; }
        }

        /// <summary>
        /// ApplySortCore で適用されたソートに関する情報を削除します。
        /// </summary>
        protected override void RemoveSortCore()
        {
            this.sortDirection = ListSortDirection.Ascending;
            this.sortProperty = null;
            this.isSorted = false;
        }

        /// <summary>
        /// 指定されたプロパティおよび方向でソートを行います。
        /// </summary>
        /// <param name="prop">抽象化プロパティ</param>
        /// <param name="direction">並べ替え操作の方向</param>
        protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
        {
            // ソートに使う情報を記録
            this.sortProperty = prop;
            this.sortDirection = direction;

            // ソートを行うリストを取得
            var list = Items as List<T>;
            if (list == null)
            {
                return;
            }

            // ソート処理
            list.Sort(this.Compare);

            // ソート完了を記録
            this.isSorted = true;

            // ListChanged イベントを発生させます
            this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

        /// <summary>
        /// 比較処理を行います。
        /// </summary>
        /// <param name="lhs">左側の値</param>
        /// <param name="rhs">右側の値</param>
        /// <returns>比較結果</returns>
        private int Compare(T lhs, T rhs)
        {
            // 比較を行う
            var result = this.OnComparison(lhs, rhs);
            
            // 昇順の場合 そのまま、降順の場合 反転させる
            return (this.sortDirection == ListSortDirection.Ascending) ? result : -result;
        }

        /// <summary>
        /// 昇順として比較処理を行います。
        /// </summary>
        /// <param name="lhs">左側の値</param>
        /// <param name="rhs">右側の値</param>
        /// <returns>比較結果</returns>
        private int OnComparison(T lhs, T rhs)
        {
            object lhsValue = (lhs == null) ? null : this.sortProperty.GetValue(lhs);
            object rhsValue = (rhs == null) ? null : this.sortProperty.GetValue(rhs);

            if (lhsValue == null)
            {
                return (rhsValue == null) ? 0 : -1;
            }

            if (rhsValue == null)
            {
                return 1;
            }

            if (lhsValue is IComparable)
            {
                return ((IComparable)lhsValue).CompareTo(rhsValue);
            }
            
            if (lhsValue.Equals(rhsValue))
            {
                return 0;
            }

            return lhsValue.ToString().CompareTo(rhsValue.ToString());
        }
    }
}

実装サンプル

フォームには dataGridView1 という DataGridView が配置されている前提で SortableBindingList の使用例を以下に載せます。

Form1.cs

public partial class Form1 : Form
{
    public Form1()
    {
        this.InitializeComponent();

        var list = new SortableBindingList<UserModel>()
        {
            new UserModel()
            {
                Id = "0010",
                FirstName = "Kurihara",
                LastName = "Yuki",
                Email = "yuki.kurihara@gmail.com",
                Password = "*****"
            },
            new UserModel()
            {
                Id = "0020",
                FirstName = "Momotsuki",
                LastName = "Shinya",
                Email = "shinya.momotsuki@gmail.com",
                Password = "*****"
            }
        };

        this.dataGridView1.DataSource = list;
    }
}

ソートできない状態にする場合は BindingSource を挟んで DataGridView.DataSource へリストを設定していましたが、 SortableBindingList を利用する場合はそのまま DataGridView.DataSource へリストを設定できます。

これを実行すると、以下のようにカラムタイトルを選択してソートできるようになり、ソート方向を示す三角アイコンが表示されるようになります。

参考記事

C# の DataGridView で カスタムデータ を 利用する 方法

Windowsフォームアプリケーションで利用する DataGridView において、 独自に作ったモデルクラスを表示させようとするとひと手間必要。 …といっても BindingSource を挟むだけで表示、追加、削除、変更ができるようになります。

以下ではそのサンプルコードを見ながら実装方法を紹介します。

目次

カスタムデータ を 設定する

作成するコードは「モデルとなるクラス」と「フォームクラス」の2種類だけです。 以下にファイル一覧を記載します。 「モデルとなるクラス」がタイトルにもある カスタムデータ に相当します。

  • UserModel.cs
  • Form1.cs

自動生成される Form1.Designer.cs は割愛します。

サンプルコード

UserModel.cs

public class UserModel
{
    public string Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string Email { get; set; }

    public string Password { get; set; }
}

Form1.cs

using System.Collections.Generic;
using System.Windows.Forms;

public partial class Form1 : Form
{
    private BindingSource wrapper;

    private List<UserModel> original;

    public Form1()
    {
        this.InitializeComponent();

        this.original = new List()
        {
            new UserModel()
            {
                Id = "0010",
                FirstName = "Kurihara",
                LastName = "Yuki",
                Email = "yuki.kurihara@gmail.com",
                Password = "*****"
            },
            new UserModel()
            {
                Id = "0020",
                FirstName = "Momotsuki",
                LastName = "Shinya",
                Email = "shinya.momotsuki@gmail.com",
                Password = "*****"
            }
        };

        this.wrapper = new BindingSource()
        {
            DataSource = this.original
        };

        this.dataGridView1.DataSource = this.wrapper;
    }
}

UserModel.cs は説明することがないので、Form1.cs に記載している バインド 部分を説明します。

ポイントは何といっても 34行目 ~ 37行目 の BindingSource へいったん代入している箇所。 DataGridView.DataSource へ直接 List<T> を代入してもうまく表示できませんが、 BindingSource を挟むことで上手く表示できるようになります。

コードによる変更を画面へ反映させる

DataGridView.DataSouce に設定した BindingSource に対して操作することで、項目の追加・変更・削除を画面反映させられます。 具体的なコードは以下でそれぞれ見ていきます。

追加

BindingSource.Add(object) を利用して項目追加をします。

    private void button1_Click(object sender, System.EventArgs e)
    {
        this.wrapper.Add(new UserModel()
        {
            Id = System.DateTime.Now.ToString(),
            FirstName = "Kurihara",
            LastName = "Yuki",
            Email = "yuki.kurihara@gmail.com",
            Password = "*****"
        });
    }

変更

変更は元データに対して操作した後、BindngSouce.ResetItem(index) を利用して画面反映を行います。

    private void button2_Click(object sender, System.EventArgs e)
    {
        var index = 0;
        this.original[index].Id = System.DateTime.Now.ToString();
        this.wrapper.ResetItem(index);
    }

削除

削除は追加と似ていて BindingSource.RemoveAt(index) で行えます。

    private void button3_Click(object sender, System.EventArgs e)
    {
        this.wrapper.RemoveAt(0);
    }

列タイトルをカスタマイズする

自動生成される列タイトルはカスタムクラスのプロパティ名そのままなので、日本語表示しようとするともうひと手間必要になります。 以下ではその方法について見ていきます。

列タイトルを自動生成させない

以下のサンプルコードのように DataGridView.AutoGenerateColumns を設定することで制御できます。 このプロパティはデザイナで DataGridView を選択したときに表示される プロパティ画面 のリストに含まれていません。 なので、別途コードを記述する必要があります。 記述場所はコンストラクタの InitializeComponent が終わった直後くらいで良いかと思います。

this.dataGridView1.AutoGenerateColumns = false;

列タイトルに任意の項目を設定する

任意項目の追加はデザイナから行えます。 デザイナで列タイトルを作成していき、それぞれにどのプロパティを割り当てるか設定することで、日本語名の列タイトルが作成できます。 具体的な手順例は以下に載せます。

  1. DataGridView 右上のオプションを選択

  2. 展開されたメニューから [列を編集...] を選択

  3. 「列の編集」ダイアログの「追加」ボタンを押下

  4. 「列の追加」ダイアログで「名前」「ヘッダーテキスト」を入力して「追加」を押下

  5. 追加された列項目を選択し、DataPropertyName にバインドしたいプロパティ名を設定

  6. 一通り設定が終わったら「OK」を選択して閉じる

  7. 設定完了


ざっと カスタムデータ を利用した DataGridView の使い方が確認できたかと思います。 とりあえずは基本的な操作ができる部分だけでしたが… この後は「ソートできる」ようにする方法をまとめていきたいと思います(…いつかやる!)

C# で 実行中 アセンブリ の ファイルパス を 取得する 方法

実行中ファイル または 実行中アセンブリ のファイルパスを取得する サンプルコード を以下にまとめます。

以下の サンプルコード では、実行中アセンブリが存在するディレクトリを取得したいます。 実行中アセンブリのファイルパスを取得した後、 Path.GetDirectoryName() を利用してディレクトリパスを取得しています。

サンプルコード

namespace Sample
{
    using System.IO;
    using System.Reflection;

    public class Config
    {
        /// <summary>
        /// 設定ファイル名
        /// </summary>
        private static string fileName = @"app.config";

        /// <summary>
        /// 設定ファイルパス
        /// </summary>
        private static string filePath = Path.Combine(
            Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
            Config.fileName);

        /// <summary>
        /// Config クラスのインスタンスを初期化します。
        /// </summary>
        public Config()
        {
        }
    }
}

…で、結論ですが、実行中アセンブリ情報が取得できれば良いので、以下のどちらかでファイルパスを取得することができます。

staticなフィールドで取得する場合

Assembly.GetExecutingAssembly().Location

インスタンス中で取得する場合

this.GetType().Assembly.Location