NFH.FileEmbed by Natalie Howes
NuGet / site data
Details
Info
Name: NFH.FileEmbed
A source generator for embedding resource files directly into your assembly. Access them as a ReadOnlySpan<byte>, with no allocations or reflection needed.
Author: Natalie Howes
NuGet: https://www.nuget.org/packages/NFH.FileEmbed/
You can find more details at https://github.com/SirCxyrtyx/FileEmbed
Author
Natalie Howes
Original Readme
C# FileEmbed
A source generator for embedding resource files directly into your assembly. Access them as a ReadOnlySpan<byte>
, with no allocations or reflection needed.
Add the package to your application using
dotnet add package NFH.FileEmbed
You will probably wish to add PrivateAssets="all"
to the PackageReference
for this package in your csproj, to prevent this becoming a dependency (as it's only needed at compile time).
Example Usage
//attribute is in this namespace
using FileEmbed;
namespace EmbedExample;
//partial methods must be in partial types
public static partial class Program
{
//Place the attribute on a static partial method that returns a ReadOnlySpan<byte>
[FileEmbed(@"Capture.PNG")]
public static partial ReadOnlySpan<byte> Bytes();
//works in any type that can contain a static method
private partial record struct MyStruct
{
//Path is relative to your project directory (specifically, the ProjectDir MSBuild property)
[FileEmbed(@"Resources\Capture.7z")]
internal static partial ReadOnlySpan<byte> StructBytes();
}
public partial interface IExampleInterface
{
//two optional arguments, Offset and Length, allow you to embed a slice of the file
[FileEmbed(@"Resources\Capture.7z", 4, 8)]
internal static partial ReadOnlySpan<byte> InterfaceBytes();
}
public static void Main()
{
Console.WriteLine($"{Bytes().Length} bytes");
Console.WriteLine($"{MyStruct.StructBytes().Length} bytes");
Console.WriteLine($"{IExampleInterface.InterfaceBytes().Length} bytes");
}
}
Autogenerated code for IExampleInterface.InterfaceBytes
:
namespace EmbedExample
{
partial class Program
{
partial interface IExampleInterface
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("FileEmbed", "0.1.0.0")]
internal static partial global::System.ReadOnlySpan<byte> InterfaceBytes() => new byte[] \{ 39,28,0,4,115,228,9,158, };
}
}
}
Limitations
This doesn't work so well for input files larger than 1MB unfortunately. The source generator itself can handle large files just fine, but, in my experience, Visual Studio chokes on the generated output, using huge amounts of memory after the files are generated. I have not yet investigated why. To protect users of this source generator from accidently locking up VS, it imposes a 1MB limit on input files. This can be overriden if you wish to try using this with larger files. To do so, put this in your csproj file:
<!-- To set FileEmbed_MaxEmbedSize, you must first make it visible to the compiler -->
<ItemGroup>
<CompilerVisibleProperty Include="FileEmbed_MaxEmbedSize" />
</ItemGroup>
<PropertyGroup>
<FileEmbed_MaxEmbedSize>SIZE_IN_BYTES_GOES_HERE</FileEmbed_MaxEmbedSize>
</PropertyGroup>
About
Generating embedded files
How to use
Example (source csproj, source files)
- CSharp Project
- Program.cs
- TestData.cs
- Countries.txt
This is the CSharp Project that references NFH.FileEmbed
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="TestData\Countries.txt" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NFH.FileEmbed" Version="0.1.0-beta" />
</ItemGroup>
<PropertyGroup>
<AdditionalFileItemNames>$(AdditionalFileItemNames);EmbeddedResource</AdditionalFileItemNames>
</PropertyGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<!--<ItemGroup>
<CompilerVisibleProperty Include="FileEmbed_MaxEmbedSize" />
</ItemGroup>
<PropertyGroup>
<FileEmbed_MaxEmbedSize>SIZE_IN_BYTES_GOES_HERE</FileEmbed_MaxEmbedSize>
</PropertyGroup>-->
</Project>
This is the use of NFH.FileEmbed in Program.cs
// See https://aka.ms/new-console-template for more information
using EmbedDemo;
using System.Text;
Console.WriteLine("Hello, World!");
var data= TestData.Countries();
Console.WriteLine(Encoding.UTF8.GetString(data) );
This is the use of NFH.FileEmbed in TestData.cs
using FileEmbed;
namespace EmbedDemo;
public static partial class TestData
{
[FileEmbed(@"TestData\Countries.txt")]
public static partial ReadOnlySpan<byte> Countries();
}
This is the use of NFH.FileEmbed in Countries.txt
USA
Germany
France
Romania
Italy
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- EMBEDDED__Countries.txt.g.cs
- FileEmbedAttribute.g.cs
namespace EmbedDemo
{
partial class TestData
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("FileEmbed", "0.1.0.0")]
public static partial global::System.ReadOnlySpan<byte> Countries() => "USA\r\nGermany\r\nFrance\r\nRomania\r\nItaly\r\n"u8;
}
}
namespace FileEmbed
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("FileEmbed", "0.1.0.0")]
[global::System.Diagnostics.Conditional("FILE_EMBED_KEEP_SOURCE_GENERATOR_ATTRIBUTE")]
[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false)]
internal class FileEmbedAttribute : global::System.Attribute
{
public string FilePath \{ get; }
public long Offset \{ get; }
public int Length \{ get; }
public FileEmbedAttribute(string filePath) : this(filePath, 0, -1) \{ }
public FileEmbedAttribute(string filePath, long offset) : this(filePath, offset, -1) \{ }
public FileEmbedAttribute(string filePath, long offset, int length)
{
FilePath = filePath;
Offset = offset;
Length = length;
}
}
}
Useful
Download Example (.NET C#)
Share NFH.FileEmbed
https://ignatandrei.github.io/RSCG_Examples/v2/docs/NFH.FileEmbed
aaa
Category "FilesToCode" has the following generators:
1 Chorn.EmbeddedResourceAccessGenerator
3 Datacute.EmbeddedResourcePropertyGenerator
6 LingoGen
12 RSCG_Utils
16 Weave