Nabs.Launchpad.Core.Resources
10.0.219
Prefix Reserved
dotnet add package Nabs.Launchpad.Core.Resources --version 10.0.219
NuGet\Install-Package Nabs.Launchpad.Core.Resources -Version 10.0.219
<PackageReference Include="Nabs.Launchpad.Core.Resources" Version="10.0.219" />
<PackageVersion Include="Nabs.Launchpad.Core.Resources" Version="10.0.219" />
<PackageReference Include="Nabs.Launchpad.Core.Resources" />
paket add Nabs.Launchpad.Core.Resources --version 10.0.219
#r "nuget: Nabs.Launchpad.Core.Resources, 10.0.219"
#:package Nabs.Launchpad.Core.Resources@10.0.219
#addin nuget:?package=Nabs.Launchpad.Core.Resources&version=10.0.219
#tool nuget:?package=Nabs.Launchpad.Core.Resources&version=10.0.219
Nabs Launchpad Core Resources Library
The Nabs Launchpad Core Resources library provides utilities for loading and accessing embedded resources from .NET assemblies. This library simplifies the process of working with embedded files such as text documents, JSON files, images, and other binary resources at runtime.
Key Features
- Multi-Assembly Support: Load resources from one or multiple assemblies simultaneously
- Type-Safe Resource Discovery: Query and filter resources using strongly-typed predicates
- Multiple Content Formats: Retrieve resources as streams, byte arrays, or text
- Result Pattern Integration: Uses Ardalis.Result for consistent error handling
- Resource Enumeration: List and discover available embedded resources across assemblies
- Single Resource Validation: Ensures predicates match exactly one resource for content methods
- UTF-8 Text Support: Automatic UTF-8 encoding for text resources
Core Components
EmbeddedResourceLoader
The main class for loading embedded resources from assemblies. It provides methods to query and retrieve embedded resources in various formats.
ResourceInfo
A record struct that represents metadata about an embedded resource, including its path and the assembly it belongs to.
Usage Examples
Basic Resource Loading
// Initialize the loader with one or more assembly types
var loader = new EmbeddedResourceLoader(typeof(MyClass), typeof(AnotherClass));
// Get resource information items
var resourceInfos = loader.GetResourceInfoItems(x => x.Path.EndsWith(".json"));
// Load resource as text
var textResult = loader.GetResourceTextContent(x => x.Path.EndsWith("config.json"));
if (textResult.IsSuccess)
{
var jsonContent = textResult.Value;
// Process the JSON content
}
// Load resource as stream
var streamResult = loader.GetResourceStreamContent(x => x.Path.EndsWith("template.html"));
if (streamResult.IsSuccess)
{
using var stream = streamResult.Value;
// Process the stream
}
// Load resource as bytes (useful for images, binary files)
var bytesResult = loader.GetResourceBytesContent(x => x.Path.EndsWith("logo.png"));
if (bytesResult.IsSuccess)
{
var imageBytes = bytesResult.Value;
// Process the binary data
}
Loading JSON Configuration
var loader = new EmbeddedResourceLoader(typeof(Program));
// Load JSON configuration file
var configResult = loader.GetResourceTextContent(x =>
x.Path.EndsWith("appsettings.embedded.json"));
if (configResult.IsSuccess)
{
var config = JsonSerializer.Deserialize<AppSettings>(configResult.Value);
// Use configuration
}
Loading Multiple Text Files
var loader = new EmbeddedResourceLoader(typeof(TemplateEngine));
// Get all template files
var templates = loader.GetResourceInfoItems(x =>
x.Path.Contains(".Templates.") && x.Path.EndsWith(".txt"));
foreach (var template in templates)
{
var contentResult = loader.GetResourceTextContent(x => x.Path == template.Path);
if (contentResult.IsSuccess)
{
Console.WriteLine($"Template: {template.Path}");
Console.WriteLine(contentResult.Value);
}
}
Loading Image Resources
var loader = new EmbeddedResourceLoader(typeof(ImageResources));
// Load company logo
var logoResult = loader.GetResourceBytesContent(x =>
x.Path.EndsWith("company-logo.png"));
if (logoResult.IsSuccess)
{
var imageBytes = logoResult.Value;
// Save to file
await File.WriteAllBytesAsync("logo.png", imageBytes);
// Or use directly in memory
using var ms = new MemoryStream(imageBytes);
var image = Image.Load(ms);
}
Loading SQL Scripts
var loader = new EmbeddedResourceLoader(typeof(DatabaseMigration));
// Load migration script
var scriptResult = loader.GetResourceTextContent(x =>
x.Path.EndsWith("001_InitialSchema.sql"));
if (scriptResult.IsSuccess)
{
await connection.ExecuteAsync(scriptResult.Value);
}
Loading HTML Templates
var loader = new EmbeddedResourceLoader(typeof(EmailService));
// Load email template
var templateResult = loader.GetResourceTextContent(x =>
x.Path.EndsWith("WelcomeEmail.html"));
if (templateResult.IsSuccess)
{
var html = templateResult.Value
.Replace("{{UserName}}", userName)
.Replace("{{ActivationLink}}", link);
await SendEmailAsync(html);
}
Discovering Available Resources
var loader = new EmbeddedResourceLoader(typeof(MyApp));
// List all embedded resources
var allResources = loader.GetResourceInfoItems(x => true);
foreach (var resource in allResources)
{
Console.WriteLine($"Assembly: {resource.Assembly.GetName().Name}");
Console.WriteLine($"Path: {resource.Path}");
}
Filtering by Namespace Pattern
var loader = new EmbeddedResourceLoader(typeof(LocalizationResources));
// Get all localization resources
var localizationFiles = loader.GetResourceInfoItems(x =>
x.Path.Contains(".Localization.") &&
x.Path.EndsWith(".resx"));
foreach (var file in localizationFiles)
{
Console.WriteLine($"Localization file: {file.Path}");
}
API Reference
EmbeddedResourceLoader
Constructor
public EmbeddedResourceLoader(params Type[] relativeAssemblyTypes)
Initializes the loader with assemblies determined by the provided types.
Parameters:
relativeAssemblyTypes: One or more types used to identify which assemblies to scan for embedded resources
Example:
var loader = new EmbeddedResourceLoader(typeof(MyClass), typeof(OtherClass));
Properties
Warnings
public List<string> Warnings { get; }
Gets a list of warnings encountered during resource loading operations.
Methods
GetResourceInfoItems
public IEnumerable<ResourceInfo> GetResourceInfoItems(
Func<ResourceInfo, bool> predicate)
Returns all resource information items that match the predicate.
Parameters:
predicate: Function to filter resources
Returns: Enumerable collection of matching resource information
Example:
var jsonFiles = loader.GetResourceInfoItems(x => x.Path.EndsWith(".json"));
GetResourceStreamContent
public Result<Stream> GetResourceStreamContent(
Func<ResourceInfo, bool> predicate)
Retrieves a single resource as a stream. Returns an error if no resource or multiple resources match the predicate.
Parameters:
predicate: Function to identify the specific resource
Returns: Result<Stream> containing the resource stream or error
Important: The predicate must match exactly one resource.
Example:
var streamResult = loader.GetResourceStreamContent(x =>
x.Path == "MyNamespace.Data.template.xml");
GetResourceBytesContent
public Result<byte[]> GetResourceBytesContent(
Func<ResourceInfo, bool> predicate)
Retrieves a single resource as a byte array. Returns an error if no resource or multiple resources match the predicate.
Parameters:
predicate: Function to identify the specific resource
Returns: Result<byte[]> containing the resource bytes or error
Important: The predicate must match exactly one resource.
Example:
var bytesResult = loader.GetResourceBytesContent(x =>
x.Path.EndsWith("icon.ico"));
GetResourceTextContent
public Result<string> GetResourceTextContent(
Func<ResourceInfo, bool> predicate)
Retrieves a single resource as a UTF-8 encoded string. Returns an error if no resource or multiple resources match the predicate.
Parameters:
predicate: Function to identify the specific resource
Returns: Result<string> containing the resource text or error
Important: The predicate must match exactly one resource.
Example:
var textResult = loader.GetResourceTextContent(x =>
x.Path.EndsWith("ReadMe.txt"));
ResourceInfo
Properties
Path
public string Path { get; }
Gets the full manifest resource name/path.
Assembly
public Assembly Assembly { get; }
Gets the assembly containing the resource.
Architecture and Design Patterns
Assembly Scanning
On construction, the loader scans all specified assemblies and caches their manifest resource names for efficient querying.
Result Pattern
All content retrieval methods return Result<T> objects for consistent error handling without exceptions.
Single Resource Validation
Content methods enforce that predicates match exactly one resource to prevent ambiguity.
Stream Management
Streams returned from GetResourceStreamContent should be disposed by the caller using using statements.
Error Handling
All content retrieval methods return Result<T> objects that indicate success or failure:
- Success: The resource was found and loaded successfully
- Error: No matching resource found, multiple resources matched, or a loading error occurred
Common error scenarios:
- "No resource info items found." - The predicate didn't match any resources
- "More than one resource info item found." - The predicate matched multiple resources (content methods require a single match)
Handling Errors
var result = loader.GetResourceTextContent(x => x.Path.EndsWith("config.json"));
if (result.IsSuccess)
{
var content = result.Value;
// Use content
}
else
{
foreach (var error in result.Errors)
{
Console.WriteLine($"Error: {error}");
}
}
Error Prevention
// Bad: Ambiguous predicate
var result = loader.GetResourceTextContent(x => x.Path.Contains(".json"));
// Might match multiple files!
// Good: Specific predicate
var result = loader.GetResourceTextContent(x =>
x.Path == "MyApp.Config.appsettings.json");
Best Practices
1. Use Specific Predicates
// Good: Specific path
x => x.Path == "MyApp.Resources.Templates.email.html"
// Bad: Might match multiple files
x => x.Path.Contains("email")
2. Check for Single Match First
var matches = loader.GetResourceInfoItems(x => x.Path.EndsWith(".config"));
if (matches.Count() == 1)
{
var content = loader.GetResourceTextContent(x => x.Path.EndsWith(".config"));
}
else
{
Console.WriteLine($"Found {matches.Count()} matches - need to be more specific");
}
3. Dispose Streams Properly
var streamResult = loader.GetResourceStreamContent(predicate);
if (streamResult.IsSuccess)
{
using var stream = streamResult.Value;
// Process stream
} // Stream disposed here
4. Use Assembly Types Strategically
// Load resources from specific assemblies
var loader = new EmbeddedResourceLoader(
typeof(CoreResources), // Core assembly
typeof(LocalizationData), // Localization assembly
typeof(TemplateEngine) // Templates assembly
);
5. Cache Loader Instances
// Create once, use many times
private static readonly EmbeddedResourceLoader _loader =
new(typeof(Program));
public string GetTemplate(string name)
{
var result = _loader.GetResourceTextContent(x => x.Path.EndsWith(name));
return result.IsSuccess ? result.Value : string.Empty;
}
6. Handle Encoding Properly
// GetResourceTextContent uses UTF-8 by default
// For other encodings, use stream and specify:
var streamResult = loader.GetResourceStreamContent(predicate);
if (streamResult.IsSuccess)
{
using var reader = new StreamReader(
streamResult.Value,
Encoding.GetEncoding("ISO-8859-1"));
var text = reader.ReadToEnd();
}
Embedded Resource Configuration
Project File Setup
<ItemGroup>
<EmbeddedResource Include="Resources\Templates\*.html" />
<EmbeddedResource Include="Resources\Config\*.json" />
<EmbeddedResource Include="Resources\Images\*.png" />
<EmbeddedResource Remove="Resources\Temp\**\*" />
</ItemGroup>
Naming Conventions
Embedded resources use the following naming pattern:
{DefaultNamespace}.{RelativePath}.{FileName}
Example:
- Project:
MyApp - File:
Resources/Templates/email.html - Resource Name:
MyApp.Resources.Templates.email.html
Testing
The library includes comprehensive unit tests demonstrating various usage patterns:
- Loading text resources
- Loading JSON resources (arrays and objects)
- Loading binary resources (images)
- Handling missing resources
- Handling ambiguous predicates (multiple matches)
Example Unit Test
[Fact]
public void GetResourceTextContent_ValidResource_ReturnsContent()
{
// Arrange
var loader = new EmbeddedResourceLoader(typeof(TestResources));
// Act
var result = loader.GetResourceTextContent(x =>
x.Path.EndsWith("TestFile.txt"));
// Assert
result.IsSuccess.Should().BeTrue();
result.Value.Should().NotBeNullOrEmpty();
}
[Fact]
public void GetResourceTextContent_MissingResource_ReturnsError()
{
// Arrange
var loader = new EmbeddedResourceLoader(typeof(TestResources));
// Act
var result = loader.GetResourceTextContent(x =>
x.Path.EndsWith("NonExistent.txt"));
// Assert
result.IsSuccess.Should().BeFalse();
result.Errors.Should().Contain("No resource info items found.");
}
Integration with Other Libraries
With Nabs.Launchpad.Core.Serialisation
var loader = new EmbeddedResourceLoader(typeof(Config));
var jsonResult = loader.GetResourceTextContent(x =>
x.Path.EndsWith("settings.json"));
if (jsonResult.IsSuccess)
{
var settings = DefaultJsonSerializer.Deserialize<AppSettings>(jsonResult.Value);
}
With Nabs.Launchpad.Core.Persistence
// Load SQL migration scripts
var loader = new EmbeddedResourceLoader(typeof(Migrations));
var scripts = loader.GetResourceInfoItems(x =>
x.Path.Contains(".Migrations.") && x.Path.EndsWith(".sql"));
foreach (var script in scripts.OrderBy(x => x.Path))
{
var sqlResult = loader.GetResourceTextContent(x => x.Path == script.Path);
if (sqlResult.IsSuccess)
{
await dbContext.Database.ExecuteSqlRawAsync(sqlResult.Value);
}
}
Troubleshooting
Resource Not Found
Issue: GetResourceTextContent returns "No resource info items found"
Solutions:
- Verify the file is marked as
EmbeddedResourcein the.csprojfile - Check the exact resource path using
GetResourceInfoItems(x => true) - Ensure you're passing the correct assembly type to the constructor
- Verify the file exists in the project
Multiple Resources Matched
Issue: GetResourceTextContent returns "More than one resource info item found"
Solutions:
- Use more specific predicates (include more of the path)
- Use the exact resource path:
x => x.Path == "Full.Resource.Path.file.txt" - List all matches first with
GetResourceInfoItemsto see what matched
Wrong Content Encoding
Issue: Text content appears garbled
Solutions:
GetResourceTextContentuses UTF-8 encoding- For other encodings, use
GetResourceStreamContentwith a customStreamReader - Save the source file with UTF-8 encoding
Performance Issues
Issue: Slow resource loading
Solutions:
- Create the
EmbeddedResourceLoaderonce and reuse it (it caches resource names) - Don't create new loaders for each resource access
- Consider lazy loading for large resources
Dependencies
- Ardalis.Result: For result pattern implementation and error handling
Related Libraries
- Nabs.Launchpad.Core.Serialisation: For deserializing JSON/CSV resources
- Nabs.Launchpad.Core.Persistence: For loading SQL scripts and migrations
- Nabs.Launchpad.Core.SeedData: For loading seed data from embedded resources
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Ardalis.Result (>= 10.1.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 10.0.219 | 89 | 1/5/2026 | |
| 10.0.218 | 85 | 1/4/2026 | |
| 10.0.217 | 100 | 1/4/2026 | |
| 10.0.216 | 94 | 1/4/2026 | |
| 10.0.215 | 96 | 1/4/2026 | |
| 10.0.214 | 97 | 1/1/2026 | |
| 10.0.213 | 97 | 1/1/2026 | |
| 10.0.212 | 94 | 1/1/2026 | |
| 10.0.211 | 93 | 12/31/2025 | |
| 10.0.210 | 102 | 12/30/2025 | |
| 10.0.209 | 98 | 12/30/2025 | |
| 10.0.208 | 98 | 12/30/2025 | |
| 10.0.207 | 102 | 12/29/2025 | |
| 10.0.206 | 96 | 12/29/2025 | |
| 10.0.205 | 181 | 12/24/2025 | |
| 10.0.204 | 185 | 12/21/2025 | |
| 10.0.203 | 280 | 12/18/2025 | |
| 10.0.202 | 282 | 12/17/2025 | |
| 10.0.200 | 277 | 12/17/2025 | |
| 10.0.199 | 437 | 12/10/2025 | |
| 10.0.197 | 175 | 12/5/2025 | |
| 10.0.196 | 681 | 12/3/2025 | |
| 10.0.195 | 676 | 12/3/2025 | |
| 10.0.194 | 680 | 12/3/2025 | |
| 10.0.193 | 683 | 12/2/2025 | |
| 10.0.192 | 187 | 11/28/2025 | |
| 10.0.190 | 197 | 11/27/2025 | |
| 10.0.189 | 180 | 11/23/2025 | |
| 10.0.187 | 181 | 11/23/2025 | |
| 10.0.186 | 164 | 11/23/2025 | |
| 10.0.184 | 415 | 11/20/2025 | |
| 10.0.181-rc3 | 282 | 11/11/2025 | |
| 10.0.180 | 302 | 11/11/2025 | |
| 10.0.179-rc2 | 293 | 11/11/2025 | |
| 10.0.178-rc2 | 255 | 11/10/2025 | |
| 10.0.177-rc2 | 242 | 11/10/2025 | |
| 10.0.176-rc2 | 198 | 11/6/2025 | |
| 10.0.175-rc2 | 207 | 11/6/2025 | |
| 10.0.174-rc2 | 202 | 11/5/2025 |