Oakrey.Applications.FileParsing 1.0.1

dotnet add package Oakrey.Applications.FileParsing --version 1.0.1
                    
NuGet\Install-Package Oakrey.Applications.FileParsing -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Oakrey.Applications.FileParsing" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Oakrey.Applications.FileParsing" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Oakrey.Applications.FileParsing" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Oakrey.Applications.FileParsing --version 1.0.1
                    
#r "nuget: Oakrey.Applications.FileParsing, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Oakrey.Applications.FileParsing@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Oakrey.Applications.FileParsing&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Oakrey.Applications.FileParsing&version=1.0.1
                    
Install as a Cake Tool

Oakrey.Applications.FileParsing

A .NET library providing an abstract framework for parsing files with automatic loading, change tracking, and reactive observable patterns. Designed for building file-based services that automatically parse and monitor file changes through the FileBrowsing service.

Features

Abstract Parsing Framework

  • Generic Type Support: Parse files into any strongly-typed object
  • Abstract Base Class: FileParsingServiceBase<T> for easy implementation
  • Standardized Interface: IFileParsingService<T> for consistent API

Automatic File Loading

  • Auto-Load on Startup: Optionally load files automatically at application startup
  • Browse Integration: Seamlessly integrates with IFileBrowsingService
  • File Selection Tracking: Automatically reparse when file selection changes

Reactive Observable Pattern

  • File Parsed Observable: Subscribe to FileParsed event for reactive updates
  • Behavior Subject: Current instance always available via Instance property
  • Real-Time Updates: Get notified immediately when files are parsed

Error Handling

  • User Prompts Integration: Built-in error dialogs for parse failures
  • Detailed Error Messages: Informative messages about what went wrong
  • Exception Handling: Graceful handling of file not found and parse errors

Pre-Loading Support

  • IPreLoadable Interface: Integrate with application startup sequences
  • Cancellation Support: All operations support CancellationToken
  • Exception Tracking: Observable pre-loading exceptions for startup diagnostics

Validation

  • Path Validation: IsFilePathCorrect property indicates successful parse
  • File Existence Checks: Validates file exists before parsing
  • Null Handling: Gracefully handles null or missing files

Installation

You can install the package via NuGet Package Manager, Package Manager Console or the .NET CLI.

NuGet Package Manager

  1. Open your project in Visual Studio.
  2. Navigate to Tools > NuGet Package Manager > Manage NuGet Packages for Solution....
  3. Search for Oakrey.Applications.FileParsing and click Install.

.NET CLI

Run the following command in your terminal:

dotnet add package Oakrey.Applications.FileParsing

Package Manager Console

Run the following command in your Package Manager Console:

Install-Package Oakrey.Applications.FileParsing

Prerequisites

This package requires:

  • Oakrey.Applications.FileBrowsing - For file selection and browsing
  • Oakrey.Applications.UserPrompts.Abstractions - For error dialogs
  • Oakrey.Log - For logging
  • Oakrey.Disposables - For resource management

Usage Examples

Creating a Custom File Parser (DBC Example)

using Oakrey.Applications.FileBrowsing;
using Oakrey.Applications.FileParsing;
using Oakrey.Applications.UserPrompts;
using Oakrey.DBC;

// Define your service interface
public interface IDbcService : IFileParsingService<DbcMatrix>
{
}

// Implement the parsing service
public sealed class DbcService : FileParsingServiceBase<DbcMatrix>, IDbcService
{
    public DbcService(
        IDbcServiceSettings settings,
        IFileBrowsingService fileBrowsingService,
        IUserPrompter<DbcService> userPrompter)
        : base(settings, fileBrowsingService, userPrompter)
    {
    }

    protected override string FileType => "DBC";

    protected override async Task<DbcMatrix> ParseFile(
        FileInfo file, 
        CancellationToken cancellationToken)
    {
        // Your custom parsing logic
        return await DbcMatrix.Created(file, cancellationToken);
    }
}

Creating Settings for Auto-Load

using Oakrey.Applications.FileParsing;
using Oakrey.Applications.Settings;

public interface IDbcServiceSettings : IAutoLoadServiceSettings
{
}

public sealed class DbcServiceSettings : SettingsBase, IDbcServiceSettings
{
    public DbcServiceSettings(ISettingsService<DbcServiceSettings> settingsService)
        : base(settingsService)
    {
    }

    public bool AutoLoad
    {
        get => Get<bool>();
        set => Set(value);
    }
}

Dependency Injection Setup

using Microsoft.Extensions.DependencyInjection;
using Oakrey.Applications.FileBrowsing;
using Oakrey.Applications.FileParsing.DBC;
using Oakrey.Applications.UserPrompts.Windows;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Register user prompts
        services.AddUserPromptsService();
        
        // Register file browsing for DBC files
        services.AddSingleton<IFileBrowsingServiceSettings, DbcFileBrowsingServiceSettings>();
        services.AddSingleton<IFileBrowsingService, FileBrowsingService>();
        
        // Register DBC parsing service settings
        services.AddSingleton<ISettingsService<DbcServiceSettings>, 
                             SettingsService<DbcServiceSettings>>();
        services.AddSingleton<IDbcServiceSettings, DbcServiceSettings>();
        
        // Register DBC parsing service
        services.AddSingleton<IDbcService, DbcService>();
    }
}

Using the File Parsing Service

using Oakrey.Applications.FileParsing.DBC;

public class CanManager
{
    private readonly IDbcService _dbcService;

    public CanManager(IDbcService dbcService)
    {
        _dbcService = dbcService;
        
        // Subscribe to file parse events
        _dbcService.FileParsed.Subscribe(OnDbcFileParsed);
    }

    private void OnDbcFileParsed(DbcMatrix? dbcMatrix)
    {
        if (dbcMatrix != null)
        {
            Console.WriteLine($"DBC file loaded: {_dbcService.FilePath}");
            Console.WriteLine($"Messages: {dbcMatrix.Messages.Count}");
            
            // Use the parsed data
            ProcessDbcData(dbcMatrix);
        }
        else
        {
            Console.WriteLine("No DBC file loaded");
        }
    }

    public void ProcessDbcData(DbcMatrix matrix)
    {
        // Process your parsed data
    }
}

Accessing Current Instance

public class DataViewer
{
    private readonly IDbcService _dbcService;

    public DataViewer(IDbcService dbcService)
    {
        _dbcService = dbcService;
    }

    public void DisplayCurrentData()
    {
        // Access current parsed instance
        if (_dbcService.Instance != null)
        {
            Console.WriteLine($"Current file: {_dbcService.FilePath}");
            Console.WriteLine($"Is valid: {_dbcService.IsFilePathCorrect}");
            
            var matrix = _dbcService.Instance;
            foreach (var message in matrix.Messages)
            {
                Console.WriteLine($"- {message.Name}");
            }
        }
        else
        {
            Console.WriteLine("No file currently loaded");
        }
    }
}

Manual File Loading

public class FileLoader
{
    private readonly IDbcService _dbcService;

    public FileLoader(IDbcService dbcService)
    {
        _dbcService = dbcService;
    }

    public async Task LoadSpecificFileAsync(string filePath)
    {
        var fileInfo = new FileInfo(filePath);
        
        // Manually load a specific file
        var result = await _dbcService.LoadFile(fileInfo);
        
        if (result != null)
        {
            Console.WriteLine("File loaded successfully");
        }
        else
        {
            Console.WriteLine("Failed to load file");
        }
    }

    public async Task LoadFileWithCancellationAsync(
        string filePath, 
        CancellationToken cancellationToken)
    {
        var fileInfo = new FileInfo(filePath);
        
        try
        {
            var result = await _dbcService.LoadFile(fileInfo, cancellationToken);
            
            if (result != null && !cancellationToken.IsCancellationRequested)
            {
                Console.WriteLine("File loaded successfully");
            }
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Load operation cancelled");
        }
    }
}

Pre-Loading Integration

using Oakrey.Applications;

public class ApplicationStartup
{
    private readonly IDbcService _dbcService;

    public ApplicationStartup(IDbcService dbcService)
    {
        _dbcService = dbcService;
    }

    public async Task InitializeAsync(CancellationToken cancellationToken)
    {
        // Pre-load file if AutoLoad is enabled
        // This happens automatically if the service is registered as IPreLoadable
        if (_dbcService is IPreLoadable preLoadable)
        {
            await preLoadable.Preload(cancellationToken);
            
            if (_dbcService.Instance != null)
            {
                Console.WriteLine("File pre-loaded successfully");
            }
        }
    }
}

Complete WPF ViewModel Example

using Oakrey.Applications.FileParsing.DBC;
using System.ComponentModel;
using System.Windows.Input;
using CommunityToolkit.Mvvm.Input;

public class DbcViewModel : INotifyPropertyChanged
{
    private readonly IDbcService _dbcService;
    private DbcMatrix? _currentMatrix;

    public DbcViewModel(IDbcService dbcService)
    {
        _dbcService = dbcService;
        
        // Subscribe to parse events
        _dbcService.FileParsed.Subscribe(OnDbcParsed);
        
        // Initialize with current instance
        _currentMatrix = _dbcService.Instance;
        
        LoadFileCommand = new AsyncRelayCommand<string>(LoadFileAsync);
        RefreshCommand = new RelayCommand(Refresh);
    }

    public DbcMatrix? CurrentMatrix
    {
        get => _currentMatrix;
        set
        {
            if (_currentMatrix != value)
            {
                _currentMatrix = value;
                OnPropertyChanged(nameof(CurrentMatrix));
                OnPropertyChanged(nameof(IsFileLoaded));
                OnPropertyChanged(nameof(MessageCount));
            }
        }
    }

    public bool IsFileLoaded => _dbcService.IsFilePathCorrect;
    
    public string CurrentFilePath => _dbcService.FilePath;
    
    public int MessageCount => CurrentMatrix?.Messages.Count ?? 0;

    public IAsyncRelayCommand<string> LoadFileCommand { get; }
    public ICommand RefreshCommand { get; }

    private void OnDbcParsed(DbcMatrix? matrix)
    {
        CurrentMatrix = matrix;
        OnPropertyChanged(nameof(CurrentFilePath));
    }

    private async Task LoadFileAsync(string? filePath)
    {
        if (!string.IsNullOrEmpty(filePath))
        {
            var fileInfo = new FileInfo(filePath);
            await _dbcService.LoadFile(fileInfo);
        }
    }

    private void Refresh()
    {
        CurrentMatrix = _dbcService.Instance;
    }

    public event PropertyChangedEventHandler? PropertyChanged;
    
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Creating a JSON File Parser

using Oakrey.Applications.FileBrowsing;
using Oakrey.Applications.FileParsing;
using Oakrey.Applications.UserPrompts;
using System.Text.Json;

public class JsonParsingService<T> : FileParsingServiceBase<T> where T : class
{
    public JsonParsingService(
        IAutoLoadServiceSettings settings,
        IFileBrowsingService fileBrowsingService,
        IUserPrompter<JsonParsingService<T>> userPrompter)
        : base(settings, fileBrowsingService, userPrompter)
    {
    }

    protected override string FileType => "JSON";

    protected override async Task<T> ParseFile(
        FileInfo file, 
        CancellationToken cancellationToken)
    {
        using var stream = file.OpenRead();
        var result = await JsonSerializer.DeserializeAsync<T>(
            stream, 
            cancellationToken: cancellationToken);
        
        return result ?? throw new InvalidOperationException("Failed to deserialize JSON");
    }
}

Creating an XML File Parser

using System.Xml.Serialization;

public class XmlParsingService<T> : FileParsingServiceBase<T> where T : class
{
    public XmlParsingService(
        IAutoLoadServiceSettings settings,
        IFileBrowsingService fileBrowsingService,
        IUserPrompter<XmlParsingService<T>> userPrompter)
        : base(settings, fileBrowsingService, userPrompter)
    {
    }

    protected override string FileType => "XML";

    protected override async Task<T> ParseFile(
        FileInfo file, 
        CancellationToken cancellationToken)
    {
        return await Task.Run(() =>
        {
            var serializer = new XmlSerializer(typeof(T));
            using var stream = file.OpenRead();
            var result = serializer.Deserialize(stream) as T;
            
            return result ?? throw new InvalidOperationException("Failed to deserialize XML");
        }, cancellationToken);
    }
}

API Reference

IFileParsingService<T>

Property Type Description
Instance T? Currently parsed file instance
FileParsed IObservable<T?> Observable for file parse events
FilePath string Path of the currently selected file
IsFilePathCorrect bool True if file was parsed successfully

FileParsingServiceBase<T>

Abstract base class for implementing file parsers:

Member Type Description
ParseFile(FileInfo, CancellationToken) abstract Task<T> Implement your parsing logic
FileType abstract string Display name for file type (e.g., "DBC")
LoadFile(FileInfo?, CancellationToken) Task<T?> Manually load a specific file
Preload(CancellationToken) Task Pre-load file if AutoLoad is enabled

IAutoLoadServiceSettings

Property Type Description
AutoLoad bool Enable automatic loading on startup

Architecture

Class Hierarchy

IFileParsingService<T>
    ?
FileParsingServiceBase<T> (abstract)
    ?
    inherits
    ?
YourCustomParsingService (concrete implementation)

Dependencies

  • IFileBrowsingService: Tracks file selection changes
  • IUserPrompter: Displays error dialogs
  • IAutoLoadServiceSettings: Controls auto-load behavior
  • ILogger: Logs parsing operations

Data Flow

  1. User selects file in FileBrowsingService
  2. FileParsingServiceBase detects selection change
  3. ParseFile is called automatically
  4. Result is stored in Instance property
  5. FileParsed observable emits new value
  6. Subscribers receive the parsed object

Error Handling

The service automatically handles:

  • File Not Found: Shows error dialog with file path
  • Parse Exceptions: Shows error dialog with exception message
  • Inner Exceptions: Displays inner exception details
  • Null Files: Gracefully handles null file selection

All errors are shown to the user via IUserPrompter dialogs.

When to Use

Use FileParsing when:

  • You need to parse structured file formats (JSON, XML, DBC, etc.)
  • You want automatic file reloading on selection changes
  • You need reactive updates when files are parsed
  • You want standardized error handling
  • You need integration with file browsing

Don't use when:

  • You only need to read raw file content (use File.ReadAllText)
  • You don't need change tracking or observables
  • Files are very large (consider streaming parsers)

Extension Packages

  • Oakrey.Applications.FileParsing.DBC - Specialized for DBC CAN database files

Requirements

  • .NET 10 or higher
  • Oakrey.Applications.FileBrowsing
  • Oakrey.Applications.UserPrompts.Abstractions
  • Oakrey.Log
  • Oakrey.Disposables

Project Information

Contributing

Contributions are welcome! Feel free to open issues or submit pull requests to improve the package.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net10.0-windows7.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Oakrey.Applications.FileParsing:

Package Downloads
Oakrey.Applications.FileParsing.DBC

Specialized file parsing library for DBC (CAN database) files. Built on FileParsing framework with automatic parsing into DbcMatrix objects, reactive updates, and extended file management. Features CAN message/signal access, template support, and seamless integration with Oakrey.DBC parser.

Oakrey.Applications.FileParsing.Ini

Specialized file parsing library for INI configuration files. Built on FileParsing framework with automatic parsing, reactive updates, and file browsing integration. Features auto-load support, observable patterns, and seamless integration with Oakrey.Files INI reader.

Oakrey.Applications.FileParsing.LDF

Specialized file parsing library for LDF (LIN Description File) files. Built on FileParsing framework with automatic parsing into LdfMatrix objects, reactive updates, and extended file management. Features LIN frame/signal access, schedule tables, template support, and seamless integration with Oakrey.LDF parser.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 80 3/13/2026
1.0.0 78 3/11/2026