File to CSharp Const

I was getting tired how many times I am reading from embedded resources – and finding it over and over the same code. So – what if I will transform the file into C# text ? Seems a work for Roslyn Source Code Generator – and the new one

IIncrementalGenerator

https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.md,not the old ISourceGenerator https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview

So the code reads from additional files defined in .csproj

<ItemGroup>
<AdditionalFiles Include=”Second.gen.txt” />
<AdditionalFiles Include=”first.gen.txt” />
<AdditionalFiles Include=”test\Afirst.gen.txt” />
< /ItemGroup>

and then transforms in a const:

string x= MyAdditionalFiles.Second_gen_txt;

Now,how difficult is the code?

The first version was

public void Initialize(IncrementalGeneratorInitializationContext initContext)
{
IncrementalValuesProvider&lt;AdditionalText&gt; textFiles = initContext
    .AdditionalTextsProvider
    .Where(file =&gt; file.Path.Contains(&quot;.gen.&quot;));

// read their contents and save their name
IncrementalValuesProvider&lt;(string name,string content)&gt; namesAndContents = textFiles
    .Select((text,cancellationToken) =&gt; (name: Path.GetFileName(text.Path),content: text.GetText(cancellationToken)!.ToString()));
            
// generate a class that contains their values as const strings
initContext.RegisterSourceOutput(namesAndContents,(spc,nameAndContent) =&gt;
{
                
    string nameString=nameAndContent.name
        .Replace(&quot;.&quot;,&quot;_&quot;)
        .Replace(&quot;-&quot;,&quot;_&quot;)
        ;
        
    string[] lines = nameAndContent.content
        .Split('\n','\r')
        .Where(it =&gt; it.Trim().Length &gt; 0)
        .Select(it =&gt; it.Replace(&quot;\\&quot;,&quot;\\\\&quot;))
        .Select(it =&gt; it.Replace(&quot;\&quot;&quot;,&quot;\\\&quot;&quot;))
        .Select(it =&gt; &quot;\&quot;&quot; + it + &quot;\\r\\n&quot; + &quot;\&quot;&quot;)
        .ToArray();
    string content = string.Join(&quot;\r\n+&quot;,lines);
    string hint = $&quot;MyAdditionalFiles.{nameAndContent.name}&quot;;
    var str = $@&quot;
public static partial class MyAdditionalFiles
{{
//https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/raw-string                
public const string {nameString} =  {content};
}}&quot;;
    spc.AddSource(hint,str );
});
}

But it have performed poorly ( 3 minutes build for a file with 2MB ) . I was thinking that splitting into lines and replacing quotes and / was the faulty

So raw strings,https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/raw-string,to the help – the second version is

//v1
//string[] lines = nameAndContent.content
//    .Split('\n','\r')
//    .Where(it =&gt; it.Trim().Length &gt; 0)
//    .Select(it =&gt; it.Replace(&quot;\\&quot;,&quot;\\\\&quot;))
//    .Select(it=&gt;it.Replace(&quot;\&quot;&quot;,&quot;\\\&quot;&quot;))
//    .Select(it =&gt; &quot;\&quot;&quot; + it +&quot;\\r\\n&quot;+ &quot;\&quot;&quot;)
//    .ToArray();
//string content = string.Join(&quot;\r\n+&quot;,lines);
//v2 =&gt; .net 7
string content=nameAndContent.content;       
//too much,but otherwise start counting quotes
var quotes = new string('&quot;',10);
content = quotes+&quot;\r\n&quot;+ content+&quot;\r\n&quot;+ quotes;

 

Additional details to be mentioned:

1.The Release with GitHUb Actions should also to be mentioned –the deployment to NUGET is a easy way now

2. Debugging is relative easy https://github.com/JoanComasFdz/dotnet-how-to-debug-source-generator-vs2022

3. It is a day of work to get rid of embedded files!

4. Does not work with binary files ( error with AdditionalFiles )

You can find the package at https://github.com/ignatandrei/RSCG_Utils .


Posted

in

,

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *