C#レコードクラスで作るファイルパス管理のサンプルコード2

C# コンピュータ
C#
レコードクラスでファイルパス管理クラスFielSystemPathのサンプルコードを書きました。
C#レコードクラスで作るファイルパス管理のサンプルコード
C#のレコードクラスを試してみました。サンプルコードファイル名:FileSystemPath.cspublic record class FileSystemPath{ public string Path { get; } private...

更に機能を追加しようと思い、ファイルの有無などファイルシステムに依存するコードを別クラスFileSystemPathExにまとめました。
また、FielSystemPathとは関係なく、新規にオブジェクトを作成するstaticメッソドをクラスFileSystemPathUtils.csにまとめました。

サンプルコード

ファイル名:FielSystemPath.cs

public record class FileSystemPath : IFileSystemPath
{
    public string Path { get; }
    static readonly char[] InvalidChars = ['"', '<', '>', '|', '\0'];
    static void Validation(string path)
    {
        if (string.IsNullOrWhiteSpace(path))
        {
            throw new ArgumentException("パスが空白または null です。", nameof(path));
        }
        // 無効な文字チェック
        if (path.IndexOfAny(InvalidChars) >= 0)
        {
            throw new ArgumentException($"パスに無効な文字が含まれています。{path}", nameof(path));
        }
    }
    private static string ValidateAndJoin(params string[] paths)
    {
        foreach (var path in paths)
        {
            Validation(path);
        }
        return System.IO.Path.Join(paths);
    }    
    public FileSystemPath(string path)
    {
        Validation(path);
        Path = path;
    }
    public FileSystemPath(params string[] paths)
    {
        Path = ValidateAndJoin(paths);
    }
    public FileSystemPath(List<string> pathList)
    {
        Path = ValidateAndJoin([.. pathList]);
    }

    // 文字列化
    public override string ToString() => Path;

    // 親ディレクトリを取得
    public IFileSystemPath GetDirectory()
    {
        string? dir = System.IO.Path.GetDirectoryName(this.Path);
        if (string.IsNullOrEmpty(dir))
        {
            throw new InvalidOperationException("親ディレクトリが取得できません。");
        }

        return new FileSystemPath(dir);
    }
    // ルートディレクトリか?
    public bool IsRoot()
    {
        return string.Equals(
            System.IO.Path.GetFullPath(this.Path),
            System.IO.Path.GetPathRoot(this.Path),
            StringComparison.OrdinalIgnoreCase
        );
    }
    // 拡張子を取得
    public string GetExtension() => System.IO.Path.GetExtension(this.Path);
    // ファイル名を取得
    public string GetFileName() => System.IO.Path.GetFileName(this.Path);
    // 拡張子抜きファイル名を取得
    public string GetBaseName() => System.IO.Path.GetFileNameWithoutExtension(this.Path);
    // ルートディレクトリを取得
    public IFileSystemPath GetRoot()
    {
        string rootStr = System.IO.Path.GetPathRoot(this.Path) ?? "";

        return new FileSystemPath(rootStr);
    }

    /*
    // 絶対パスを取得 (文字列操作ではなく、実行環境依存)
    public string GetFullPath() => System.IO.Path.GetFullPath(this.Path);
    */

    // 拡張子があるか?
    public bool HasExtension() => System.IO.Path.HasExtension(this.Path);

    // ルートが含まれているか?
    public bool IsPathRooted() => System.IO.Path.IsPathRooted(this.Path);

    // 連結
    public IFileSystemPath Combine(IFileSystemPath path)
    {
        string result = System.IO.Path.Combine(this.Path, path.Path);
        return new FileSystemPath(result);
    }
    // 拡張子を追加
    public IFileSystemPath AppendExtension(string ext)
    {
        if (string.IsNullOrWhiteSpace(ext))
        {
            throw new ArgumentException("拡張子が空です", nameof(ext));
        }

        // 拡張子先頭にドットがなければ追加
        if (!ext.StartsWith("."))
        {
            ext = "." + ext;
        }
        string newPath = (this.ToString() + ext);
        return new FileSystemPath(newPath);
    }
    // 拡張子の置換
    public IFileSystemPath ChangeExtension(string newExt)
    {
        if (string.IsNullOrWhiteSpace(newExt))
        {
            throw new ArgumentException("拡張子が空です", nameof(newExt));
        }

        // 拡張子先頭にドットがなければ追加
        if (!newExt.StartsWith("."))
        {
            newExt = "." + newExt;
        }

        string newPath = System.IO.Path.ChangeExtension(this.ToString(), newExt);
        return new FileSystemPath(newPath);
    } 
    // 相対パスを取得
    public IFileSystemPath GetRelativePath(IFileSystemPath basePath)
    {
        ArgumentNullException.ThrowIfNull(basePath);

        string relativePath = System.IO.Path.GetRelativePath(basePath.Path, this.Path);
        return new FileSystemPath(relativePath);
    }
    // 末尾が区切り文字か?
    public bool EndsInDirectorySeparator() => System.IO.Path.EndsInDirectorySeparator(this.Path);
    // ランダムなフォルダー名またはファイル名を返します。
    public IFileSystemPath GetRandomFileName()
    {
        string path = System.IO.Path.GetRandomFileName();
        return new FileSystemPath(path);
    }
    // ファイル パスが完全修飾されているか
    public bool IsPathFullyQualified() => System.IO.Path.IsPathFullyQualified(this.Path);
    // 末尾の区切り文字を削除
    public IFileSystemPath TrimEndingDirectorySeparator()
    {
        string path = System.IO.Path.TrimEndingDirectorySeparator(this.Path);
        return new FileSystemPath(path);
    }

}

ファイル名:FileSystemPathEx.cs


public record class FileSystemPathEx : IFileSystemPathEx
{
    IFileSystemPath _FileSystemPath;

    public IFileSystemPath InnerPath { get => _FileSystemPath; }

    // コンストラクタ
    public FileSystemPathEx(string path)
    {
        _FileSystemPath = new FileSystemPath(path);
    }

    // コンストラクタ
    public FileSystemPathEx(IFileSystemPath fileSystemPath)
    {
        _FileSystemPath = fileSystemPath;
    }

    // 絶対パスを取得 
    public IFileSystemPath GetFullPath()
    {
        string fullPath = System.IO.Path.GetFullPath(_FileSystemPath.Path);
        return new FileSystemPath(fullPath);
    }
    // ファイルの存在確認
    public bool IsFile() => System.IO.File.Exists(_FileSystemPath.Path);
    // ディレクトリの存在確認
    public bool IsDirectory() => System.IO.Directory.Exists(_FileSystemPath.Path);
    // ファイルまたはディレクトリが存在確認
    //public bool Exists() => System.IO.Path.Exists(_FileSystemPath.Path);
    public bool Exists() =>
        System.IO.File.Exists(_FileSystemPath.Path) || System.IO.Directory.Exists(_FileSystemPath.Path);

}

ファイル名:FileSystemPathUtils.cs

public class FileSystemPathUtils
{
    // 拡張子.tmpの一時ファイルをディスク上に作成し、そのファイルの完全パスを返します。
    public static IFileSystemPath GetTempFileName()
    {
        string fullPath = System.IO.Path.GetTempFileName();
        return new FileSystemPath(fullPath);
    }
    // 現在のユーザーの一時フォルダーのパスを返します。
    public static IFileSystemPath GetTempPath()
    {
        string fullPath = System.IO.Path.GetTempPath();
        return new FileSystemPath(fullPath);
    }

}

ファイル名:IFielSystemPath.cs

public interface IFileSystemPath
{
    // パス
    public string Path { get; }

    // 親ディレクトリを取得
    public IFileSystemPath GetDirectory();
    // ルートディレクトリか?
    public bool IsRoot();
    // 拡張子を取得
    public string GetExtension();
    // ファイル名を取得
    public string GetFileName();
    // 拡張子抜きファイル名を取得
    public string GetBaseName();
    // ルートディレクトリを取得
    public IFileSystemPath GetRoot();

    /*
    // 絶対パスを取得 (文字列操作ではなく、実行環境依存)
    public string GetFullPath() => System.IO.Path.GetFullPath(this.Path);
    */

    // 拡張子があるか?
    public bool HasExtension();

    // ルートが含まれているか?
    public bool IsPathRooted();

    // 連結
    public IFileSystemPath Combine(IFileSystemPath path);
    // 拡張子を追加
    public IFileSystemPath AppendExtension(string ext);
    // 拡張子の置換
    public IFileSystemPath ChangeExtension(string newExt);
    // 相対パスを取得
    public IFileSystemPath GetRelativePath(IFileSystemPath basePath);
    // 末尾が区切り文字か?
    public bool EndsInDirectorySeparator();
    // ランダムなフォルダー名またはファイル名を返します。
    public IFileSystemPath GetRandomFileName();
    // ファイル パスが完全修飾されているか
    public bool IsPathFullyQualified();
    // 末尾の区切り文字を削除
    public IFileSystemPath TrimEndingDirectorySeparator();
}

ファイル名:IFileSystemPathEx.cs

public interface IFileSystemPathEx
{
    public IFileSystemPath InnerPath { get; }

    // 絶対パスを取得 
    public IFileSystemPath GetFullPath();
    // ファイルまたはディレクトリが存在確認
    public bool Exists();
    // ファイルの存在確認
    public bool IsFile();
    // ディレクトリの存在確認
    public bool IsDirectory();

}

コメント