Category: RSCG

RSCG – RSCG_Static

 
 

name RSCG_Static
nuget https://www.nuget.org/packages/RSCG_Static/
link https://github.com/ignatandrei/RSCG_Static
author Andrei Ignat

Generate interfaces and classes from static classes

 

This is how you can use RSCG_Static .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">

	<PropertyGroup>
		<OutputType>Exe</OutputType>
		<TargetFramework>net7.0</TargetFramework>
		<ImplicitUsings>enable</ImplicitUsings>
		<Nullable>enable</Nullable>
	</PropertyGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
	<ItemGroup>
		<PackageReference Include="RSCG_Static" Version="2023.5.19.2037" />
	</ItemGroup>

</Project>


The code that you will use is


using RSCG_StaticDemo;
//for DI, register
//ISystem_DateTime  with transient for new clsSystem_DateTime()
Console.WriteLine("Hello World!");
ISystem_DateTime dateStatic = recSystem_DateTime.MakeNew();//static
ISystem_DateTime dateVar = new clsSystem_DateTime(); //variable = real 

Console.WriteLine(dateStatic.Now.Second);
Console.WriteLine(dateVar.Now.Second);
await Task.Delay(10 * 1000);
Console.WriteLine(dateStatic.Now.Second);
Console.WriteLine(dateVar.Now.Second);



namespace RSCG_StaticDemo;

public partial class StaticToInterface
{
    public Type GenerateInterfaceFromDate() => typeof(DateTime);
}


 

The code that is generated is


#nullable enable
 namespace RSCG_StaticDemo {
      public interface ISystem_DateTime {
          public System.DateTime Now  {get;}
          public System.DateTime Today  {get;}
          public System.DateTime UtcNow  {get;}
      }// interface
//now the partial class
      public record recSystem_DateTime (System.DateTime Now,System.DateTime Today,System.DateTime UtcNow) : ISystem_DateTime
      { 
            public static recSystem_DateTime MakeNew() {
            return new recSystem_DateTime(System.DateTime.Now,System.DateTime.Today,System.DateTime.UtcNow);
            } //end makenew
      } //end record
      public class clsSystem_DateTime : ISystem_DateTime 
      { 
            public System.DateTime Now  {get { return System.DateTime.Now; } }
            public System.DateTime Today  {get { return System.DateTime.Today; } }
            public System.DateTime UtcNow  {get { return System.DateTime.UtcNow; } }
       } //end class
 } // namespace
#nullable disable

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/RSCG_Static

RSCG – Microsoft.Extensions.Logging

RSCG – Microsoft.Extensions.Logging
 
 

name Microsoft.Extensions.Logging
nuget https://www.nuget.org/packages/Microsoft.Extensions.Logging/
link https://learn.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator-generators/
author Microsoft

Logging defined and compiled

 

This is how you can use Microsoft.Extensions.Logging .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
	<PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
    </PropertyGroup>
	<ItemGroup>
		<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
	</ItemGroup>
</Project>


The code that you will use is


using System.Text.Json;
using Microsoft.Extensions.Logging;

using ILoggerFactory loggerFactory = LoggerFactory.Create(
    builder =>
    //https://learn.microsoft.com/en-us/dotnet/core/extensions/console-log-formatter
    builder.AddSimpleConsole()
    //builder.AddJsonConsole(
    //    options =>
    //    options.JsonWriterOptions = new JsonWriterOptions()
    //    {
    //        Indented = true
    //    })
    ) ;

ILogger<SampleObject> logger = loggerFactory.CreateLogger<SampleObject>();
logger.LogInformation("test");
//https://learn.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator
(new LoggingSample(logger)).TestLogging();
file readonly record struct SampleObject { }



using Microsoft.Extensions.Logging;

public partial class LoggingSample
{
    private readonly ILogger _logger;

    public LoggingSample(ILogger logger)
    {
        _logger = logger;
    }

    [LoggerMessage(
        EventId = 20,
        Level = LogLevel.Critical,
        Message = "Value is {value:E}")]
    public static partial void UsingFormatSpecifier(
        ILogger logger, double value);

    [LoggerMessage(
        EventId = 9,
        Level = LogLevel.Trace,
        Message = "Fixed message",
        EventName = "CustomEventName")]
    public partial void LogWithCustomEventName();

    [LoggerMessage(
        EventId = 10,
        Message = "Welcome to {city} {province}!")]
    public partial void LogWithDynamicLogLevel(
        string city, LogLevel level, string province);

    public void  TestLogging()
    {
        LogWithCustomEventName();

        LogWithDynamicLogLevel("Vancouver", LogLevel.Warning, "BC");
        LogWithDynamicLogLevel("Vancouver", LogLevel.Information, "BC");

        UsingFormatSpecifier(_logger, 12345.6789);
    }
}

 

The code that is generated is

// <auto-generated/>
#nullable enable

    partial class LoggingSample
    {
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.7.1805")]
        private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Double, global::System.Exception?> __UsingFormatSpecifierCallback =
            global::Microsoft.Extensions.Logging.LoggerMessage.Define<global::System.Double>(global::Microsoft.Extensions.Logging.LogLevel.Critical, new global::Microsoft.Extensions.Logging.EventId(20, nameof(UsingFormatSpecifier)), "Value is {value:E}", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true }); 

        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.7.1805")]
        public static partial void UsingFormatSpecifier(global::Microsoft.Extensions.Logging.ILogger logger, global::System.Double value)
        {
            if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Critical))
            {
                __UsingFormatSpecifierCallback(logger, value, null);
            }
        }
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.7.1805")]
        private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Exception?> __LogWithCustomEventNameCallback =
            global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Trace, new global::Microsoft.Extensions.Logging.EventId(9, "CustomEventName"), "Fixed message", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true }); 

        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.7.1805")]
        public partial void LogWithCustomEventName()
        {
            if (_logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Trace))
            {
                __LogWithCustomEventNameCallback(_logger, null);
            }
        }
        /// <summary> This API supports the logging infrastructure and is not intended to be used directly from your code. It is subject to change in the future. </summary>
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.7.1805")]
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)]
        private readonly struct __LogWithDynamicLogLevelStruct : global::System.Collections.Generic.IReadOnlyList<global::System.Collections.Generic.KeyValuePair<string, object?>>
        {
            private readonly global::System.String _city;
            private readonly global::System.String _province;

            public __LogWithDynamicLogLevelStruct(global::System.String city, global::System.String province)
            {
                this._city = city;
                this._province = province;

            }

            public override string ToString()
            {
                var city = this._city;
                var province = this._province;

                return $"Welcome to {city} {province}!";
            }

            public static readonly global::System.Func<__LogWithDynamicLogLevelStruct, global::System.Exception?, string> Format = (state, ex) => state.ToString();

            public int Count => 3;

            public global::System.Collections.Generic.KeyValuePair<string, object?> this[int index]
            {
                get => index switch
                {
                    0 => new global::System.Collections.Generic.KeyValuePair<string, object?>("city", this._city),
                    1 => new global::System.Collections.Generic.KeyValuePair<string, object?>("province", this._province),
                    2 => new global::System.Collections.Generic.KeyValuePair<string, object?>("{OriginalFormat}", "Welcome to {city} {province}!"),

                    _ => throw new global::System.IndexOutOfRangeException(nameof(index)),  // return the same exception LoggerMessage.Define returns in this case
                };
            }

            public global::System.Collections.Generic.IEnumerator<global::System.Collections.Generic.KeyValuePair<string, object?>> GetEnumerator()
            {
                for (int i = 0; i < 3; i++)
                {
                    yield return this[i];
                }
            }

            global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
        }

        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.7.1805")]
        public partial void LogWithDynamicLogLevel(global::System.String city, global::Microsoft.Extensions.Logging.LogLevel level, global::System.String province)
        {
            if (_logger.IsEnabled(level))
            {
                _logger.Log(
                    level,
                    new global::Microsoft.Extensions.Logging.EventId(10, nameof(LogWithDynamicLogLevel)),
                    new __LogWithDynamicLogLevelStruct(city, province),
                    null,
                    __LogWithDynamicLogLevelStruct.Format);
            }
        }
    }

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/Microsoft.Extensions.Logging

RSCG – SkinnyControllersCommon

RSCG – SkinnyControllersCommon
 
 

name SkinnyControllersCommon
nuget https://www.nuget.org/packages/SkinnyControllersCommon
link https://github.com/ignatandrei/SkinnyControllersGenerator/
author Ignat Andrei

Automatically add controllers actions for any class injected in constructor

 

This is how you can use SkinnyControllersCommon .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="SkinnyControllersCommon" Version="2023.5.14.2055" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
  </ItemGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
</Project>


The code that you will use is


using SkinnyControllersDemo.Controllers;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddTransient<WeatherActions>();
var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();



using Microsoft.AspNetCore.Mvc;
using SkinnyControllersCommon;

namespace SkinnyControllersDemo.Controllers;
[AutoActions(template = TemplateIndicator.NoArgs_Is_Get_Else_Post, FieldsName = new[] { "*" }, ExcludeFields = new[] { "_logger" })]
[ApiController]
[Route("[controller]/[action]")]
public partial class WeatherForecastController : ControllerBase
{

    private readonly ILogger<WeatherForecastController> _logger;
    private readonly WeatherActions weather;

    public WeatherForecastController(ILogger<WeatherForecastController> logger, WeatherActions weather)
    {
        _logger = logger;
        this.weather = weather;
    }

    

}


namespace SkinnyControllersDemo.Controllers
{
    public class WeatherActions
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
        public async Task<int> MultiplyBy2(int nr)
        {
            await Task.Delay(nr);
            return nr*2;
        }
    }
}

 

The code that is generated is

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     SkinnyControllersGenerator: 
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace SkinnyControllersDemo.Controllers {
  [GeneratedCode("SkinnyControllersGenerator", "")]
  [CompilerGenerated]
  partial class WeatherForecastController{ 
    /*[HttpGet()]
    public int id(){
    System.Diagnostics.Debugger.Break();
    return 1;
    } */

      

        [HttpGet] 
        public System.Collections.Generic.IEnumerable<SkinnyControllersDemo.WeatherForecast> Get (){
            //System.Diagnostics.Debugger.Break();
            
                            return 
                        
            weather.Get();

        }
      

        [HttpPost] 
        public System.Threading.Tasks.Task<int> MultiplyBy2 (int nr){
            //System.Diagnostics.Debugger.Break();
            
                            return 
                        
            weather.MultiplyBy2(nr);

        }
      
    
  }
}              

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/SkinnyControllersCommon

RSCG – System.Text.RegularExpressions

RSCG – System.Text.RegularExpressions
 
 

name System.Text.RegularExpressions
nuget https://www.nuget.org/packages/System.Text.RegularExpressions/
link https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-source-generators/
author Microsoft

Regex compiled

 

This is how you can use System.Text.RegularExpressions .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
	<PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
    </PropertyGroup>

</Project>


The code that you will use is


using Demo;
//https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-source-generators
//https://devblogs.microsoft.com/dotnet/regular-expression-improvements-in-dotnet-7/
var x = "Abc";
Console.WriteLine(DemoRegex.EvaluateText(x));


using System.Text.RegularExpressions;

namespace Demo;

public partial class DemoRegex
{
    [GeneratedRegex("abc|def", RegexOptions.IgnoreCase, "en-US")]
    private static partial Regex AbcOrDefGeneratedRegex();

    public static bool EvaluateText(string text)
    {
        return (AbcOrDefGeneratedRegex().IsMatch(text));
        
    }
}


 

The code that is generated is

// <auto-generated/>
#nullable enable
#pragma warning disable CS0162 // Unreachable code
#pragma warning disable CS0164 // Unreferenced label
#pragma warning disable CS0219 // Variable assigned but never used

namespace Demo
{
    partial class DemoRegex
    {
        /// <remarks>
        /// Pattern explanation:<br/>
        /// <code>
        /// ○ Match with 2 alternative expressions, atomically.<br/>
        ///     ○ Match a sequence of expressions.<br/>
        ///         ○ Match a character in the set [Aa].<br/>
        ///         ○ Match a character in the set [Bb].<br/>
        ///         ○ Match a character in the set [Cc].<br/>
        ///     ○ Match a sequence of expressions.<br/>
        ///         ○ Match a character in the set [Dd].<br/>
        ///         ○ Match a character in the set [Ee].<br/>
        ///         ○ Match a character in the set [Ff].<br/>
        /// </code>
        /// </remarks>
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "7.0.8.17405")]
        private static partial global::System.Text.RegularExpressions.Regex AbcOrDefGeneratedRegex() => global::System.Text.RegularExpressions.Generated.AbcOrDefGeneratedRegex_0.Instance;
    }
}

namespace System.Text.RegularExpressions.Generated
{
    using System;
    using System.CodeDom.Compiler;
    using System.Collections;
    using System.ComponentModel;
    using System.Globalization;
    using System.Runtime.CompilerServices;
    using System.Text.RegularExpressions;
    using System.Threading;

    /// <summary>Custom <see cref="Regex"/>-derived type for the AbcOrDefGeneratedRegex method.</summary>
    [GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "7.0.8.17405")]
    file sealed class AbcOrDefGeneratedRegex_0 : Regex
    {
        /// <summary>Cached, thread-safe singleton instance.</summary>
        internal static readonly AbcOrDefGeneratedRegex_0 Instance = new();
    
        /// <summary>Initializes the instance.</summary>
        private AbcOrDefGeneratedRegex_0()
        {
            base.pattern = "abc|def";
            base.roptions = RegexOptions.IgnoreCase;
            ValidateMatchTimeout(Utilities.s_defaultTimeout);
            base.internalMatchTimeout = Utilities.s_defaultTimeout;
            base.factory = new RunnerFactory();
            base.capsize = 1;
        }
    
        /// <summary>Provides a factory for creating <see cref="RegexRunner"/> instances to be used by methods on <see cref="Regex"/>.</summary>
        private sealed class RunnerFactory : RegexRunnerFactory
        {
            /// <summary>Creates an instance of a <see cref="RegexRunner"/> used by methods on <see cref="Regex"/>.</summary>
            protected override RegexRunner CreateInstance() => new Runner();
        
            /// <summary>Provides the runner that contains the custom logic implementing the specified regular expression.</summary>
            private sealed class Runner : RegexRunner
            {
                /// <summary>Scan the <paramref name="inputSpan"/> starting from base.runtextstart for the next match.</summary>
                /// <param name="inputSpan">The text being scanned by the regular expression.</param>
                protected override void Scan(ReadOnlySpan<char> inputSpan)
                {
                    // Search until we can't find a valid starting position, we find a match, or we reach the end of the input.
                    while (TryFindNextPossibleStartingPosition(inputSpan) &&
                           !TryMatchAtCurrentPosition(inputSpan) &&
                           base.runtextpos != inputSpan.Length)
                    {
                        base.runtextpos++;
                        if (Utilities.s_hasTimeout)
                        {
                            base.CheckTimeout();
                        }
                    }
                }
        
                /// <summary>Search <paramref name="inputSpan"/> starting from base.runtextpos for the next location a match could possibly start.</summary>
                /// <param name="inputSpan">The text being scanned by the regular expression.</param>
                /// <returns>true if a possible match was found; false if no more matches are possible.</returns>
                private bool TryFindNextPossibleStartingPosition(ReadOnlySpan<char> inputSpan)
                {
                    int pos = base.runtextpos;
                    ulong charMinusLow;
                    
                    // Any possible match is at least 3 characters.
                    if (pos <= inputSpan.Length - 3)
                    {
                        // The pattern matches a character in the set [CFcf] at index 2.
                        // Find the next occurrence. If it can't be found, there's no match.
                        ReadOnlySpan<char> span = inputSpan.Slice(pos);
                        for (int i = 0; i < span.Length - 2; i++)
                        {
                            int indexOfPos = span.Slice(i + 2).IndexOfAny("CFcf");
                            if (indexOfPos < 0)
                            {
                                goto NoMatchFound;
                            }
                            i += indexOfPos;
                            
                            if (((long)((0x9000000090000000UL << (int)(charMinusLow = (uint)span[i] - 'A')) & (charMinusLow - 64)) < 0) &&
                                ((long)((0x9000000090000000UL << (int)(charMinusLow = (uint)span[i + 1] - 'B')) & (charMinusLow - 64)) < 0))
                            {
                                base.runtextpos = pos + i;
                                return true;
                            }
                        }
                    }
                    
                    // No match found.
                    NoMatchFound:
                    base.runtextpos = inputSpan.Length;
                    return false;
                }
        
                /// <summary>Determine whether <paramref name="inputSpan"/> at base.runtextpos is a match for the regular expression.</summary>
                /// <param name="inputSpan">The text being scanned by the regular expression.</param>
                /// <returns>true if the regular expression matches at the current position; otherwise, false.</returns>
                private bool TryMatchAtCurrentPosition(ReadOnlySpan<char> inputSpan)
                {
                    int pos = base.runtextpos;
                    int matchStart = pos;
                    ReadOnlySpan<char> slice = inputSpan.Slice(pos);
                    
                    // Match with 2 alternative expressions, atomically.
                    {
                        if (slice.IsEmpty)
                        {
                            return false; // The input didn't match.
                        }
                        
                        switch (slice[0])
                        {
                            case 'A' or 'a':
                                if ((uint)slice.Length < 3 ||
                                    !slice.Slice(1).StartsWith("bc", StringComparison.OrdinalIgnoreCase)) // Match the string "bc" (ordinal case-insensitive)
                                {
                                    return false; // The input didn't match.
                                }
                                
                                pos += 3;
                                slice = inputSpan.Slice(pos);
                                break;
                                
                            case 'D' or 'd':
                                if ((uint)slice.Length < 3 ||
                                    !slice.Slice(1).StartsWith("ef", StringComparison.OrdinalIgnoreCase)) // Match the string "ef" (ordinal case-insensitive)
                                {
                                    return false; // The input didn't match.
                                }
                                
                                pos += 3;
                                slice = inputSpan.Slice(pos);
                                break;
                                
                            default:
                                return false; // The input didn't match.
                        }
                    }
                    
                    // The input matched.
                    base.runtextpos = pos;
                    base.Capture(0, matchStart, pos);
                    return true;
                }
            }
        }

    }
    
    /// <summary>Helper methods used by generated <see cref="Regex"/>-derived implementations.</summary>
    [GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "7.0.8.17405")]
    file static class Utilities
    {
        /// <summary>Default timeout value set in <see cref="AppContext"/>, or <see cref="Regex.InfiniteMatchTimeout"/> if none was set.</summary>
        internal static readonly TimeSpan s_defaultTimeout = AppContext.GetData("REGEX_DEFAULT_MATCH_TIMEOUT") is TimeSpan timeout ? timeout : Regex.InfiniteMatchTimeout;
        
        /// <summary>Whether <see cref="s_defaultTimeout"/> is non-infinite.</summary>
        internal static readonly bool s_hasTimeout = s_defaultTimeout != Timeout.InfiniteTimeSpan;
    }
}

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/System.Text.RegularExpressions

RSCG – RSCG_Utils

RSCG – RSCG_Utils
 
 

name RSCG_Utils
nuget https://www.nuget.org/packages/RSCG_Utils
link https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation
author Ignat Andrei

Add files as C# consts

 

This is how you can use RSCG_Utils .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="rscgutils" Version="2023.514.835" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  
  </ItemGroup>
	<ItemGroup>
		<AdditionalFiles Include="data.gen.txt" />
	</ItemGroup>

	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>


</Project>


The code that you will use is


Console.WriteLine("Hello, World!");
string dataFromFile = MyAdditionalFiles.data_gen_txt;
Console.Write(dataFromFile);


This is a data
That you will retrieve
as C# const

 

The code that is generated is


    public static partial class MyAdditionalFiles
    {
        //https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/raw-string                
        public const string data_gen_txt =  """"""""""
This is a data
That you will retrieve
as C# const
"""""""""";
    }

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/RSCG_Utils

RSCG – System.Text.Json

 
 

name System.Text.Json
nuget https://www.nuget.org/packages/System.Text.Json/
link https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation
author Microsoft

Json Serialize without reflection

 

This is how you can use System.Text.Json .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
	<PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
    </PropertyGroup>

</Project>


The code that you will use is


using JsonSerializerOptionsExample;
using System.Text.Json;
//for asp.net core
//services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.AddContext<MyJsonContext>());
//https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/raw-string

string jsonString ="""
{
  "date": "2019-08-01T00:00:00",
  "temperatureCelsius": 25,
  "summary": "Hot"
}
""";
        WeatherForecast? weatherForecast= JsonSerializer.Deserialize(
            jsonString,
            typeof(WeatherForecast),
            new OptionsExampleContext(
                new JsonSerializerOptions(JsonSerializerDefaults.Web)))
                as WeatherForecast;
        Console.WriteLine($"Date={weatherForecast?.Date}");
        // output:
        //Date=8/1/2019 12:00:00 AM

        jsonString = JsonSerializer.Serialize(
            weatherForecast,
            typeof(WeatherForecast),
            new OptionsExampleContext(
                new JsonSerializerOptions(JsonSerializerDefaults.Web)));
        Console.WriteLine(jsonString);
jsonString = JsonSerializer.Serialize(
    weatherForecast,
    typeof(WeatherForecast),
    new OptionsExampleContext(
        new JsonSerializerOptions(JsonSerializerDefaults.General)));
Console.WriteLine(jsonString);
// output:
//{ "date":"2019-08-01T00:00:00","temperatureCelsius":25,"summary":"Hot"}



namespace JsonSerializerOptionsExample;

public class WeatherForecast
{
    public DateTime Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
}



using System.Text.Json.Serialization;

namespace JsonSerializerOptionsExample;

[JsonSerializable(typeof(WeatherForecast))]
internal partial class OptionsExampleContext : JsonSerializerContext
{
}


 

The code that is generated is

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618

namespace JsonSerializerOptionsExample
{
    internal partial class OptionsExampleContext
    {
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.DateTime>? _DateTime;
        /// <summary>
        /// Defines the source generated JSON serialization contract metadata for a given type.
        /// </summary>
        public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.DateTime> DateTime
        {
            get => _DateTime ??= Create_DateTime(Options, makeReadOnly: true);
        }
        
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.DateTime> Create_DateTime(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
        {
            global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.DateTime>? jsonTypeInfo = null;
            global::System.Text.Json.Serialization.JsonConverter? customConverter;
            if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::System.DateTime))) != null)
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.DateTime>(options, customConverter);
            }
            else
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.DateTime>(options, global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.DateTimeConverter);
            }
        
            if (makeReadOnly)
            {
                jsonTypeInfo.MakeReadOnly();
            }
        
            return jsonTypeInfo;
        }
        
    }
}

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618

namespace JsonSerializerOptionsExample
{
    
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "7.0.8.17405")]
    internal partial class OptionsExampleContext
    {
        
        private static global::System.Text.Json.JsonSerializerOptions s_defaultOptions { get; } = new global::System.Text.Json.JsonSerializerOptions()
        {
            DefaultIgnoreCondition = global::System.Text.Json.Serialization.JsonIgnoreCondition.Never,
            IgnoreReadOnlyFields = false,
            IgnoreReadOnlyProperties = false,
            IncludeFields = false,
            WriteIndented = false,
        };
        
        private static global::JsonSerializerOptionsExample.OptionsExampleContext? s_defaultContext;
        
        /// <summary>
        /// The default <see cref="global::System.Text.Json.Serialization.JsonSerializerContext"/> associated with a default <see cref="global::System.Text.Json.JsonSerializerOptions"/> instance.
        /// </summary>
        public static global::JsonSerializerOptionsExample.OptionsExampleContext Default => s_defaultContext ??= new global::JsonSerializerOptionsExample.OptionsExampleContext(new global::System.Text.Json.JsonSerializerOptions(s_defaultOptions));
        
        /// <summary>
        /// The source-generated options associated with this context.
        /// </summary>
        protected override global::System.Text.Json.JsonSerializerOptions? GeneratedSerializerOptions { get; } = s_defaultOptions;
        
        /// <inheritdoc/>
        public OptionsExampleContext() : base(null)
        {
        }
        
        /// <inheritdoc/>
        public OptionsExampleContext(global::System.Text.Json.JsonSerializerOptions options) : base(options)
        {
        }
        
        private static global::System.Text.Json.Serialization.JsonConverter? GetRuntimeProvidedCustomConverter(global::System.Text.Json.JsonSerializerOptions options, global::System.Type type)
        {
            global::System.Collections.Generic.IList<global::System.Text.Json.Serialization.JsonConverter> converters = options.Converters;
        
            for (int i = 0; i < converters.Count; i++)
            {
                global::System.Text.Json.Serialization.JsonConverter? converter = converters[i];
        
                if (converter.CanConvert(type))
                {
                    if (converter is global::System.Text.Json.Serialization.JsonConverterFactory factory)
                    {
                        converter = factory.CreateConverter(type, options);
                        if (converter == null || converter is global::System.Text.Json.Serialization.JsonConverterFactory)
                        {
                            throw new global::System.InvalidOperationException(string.Format("The converter '{0}' cannot return null or a JsonConverterFactory instance.", factory.GetType()));
                        }
                    }
        
                    return converter;
                }
            }
        
            return null;
        }
    }
}

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618

namespace JsonSerializerOptionsExample
{
    internal partial class OptionsExampleContext: global::System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver
    {
        /// <inheritdoc/>
        public override global::System.Text.Json.Serialization.Metadata.JsonTypeInfo GetTypeInfo(global::System.Type type)
        {
            if (type == typeof(global::JsonSerializerOptionsExample.WeatherForecast))
            {
                return this.WeatherForecast;
            }
        
            if (type == typeof(global::System.DateTime))
            {
                return this.DateTime;
            }
        
            if (type == typeof(global::System.Int32))
            {
                return this.Int32;
            }
        
            if (type == typeof(global::System.String))
            {
                return this.String;
            }
        
            return null!;
        }
        
        global::System.Text.Json.Serialization.Metadata.JsonTypeInfo? global::System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver.GetTypeInfo(global::System.Type type, global::System.Text.Json.JsonSerializerOptions options)
        {
            if (type == typeof(global::JsonSerializerOptionsExample.WeatherForecast))
            {
                return Create_WeatherForecast(options, makeReadOnly: false);
            }
        
            if (type == typeof(global::System.DateTime))
            {
                return Create_DateTime(options, makeReadOnly: false);
            }
        
            if (type == typeof(global::System.Int32))
            {
                return Create_Int32(options, makeReadOnly: false);
            }
        
            if (type == typeof(global::System.String))
            {
                return Create_String(options, makeReadOnly: false);
            }
        
            return null;
        }
        
    }
}

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618

namespace JsonSerializerOptionsExample
{
    internal partial class OptionsExampleContext
    {
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Int32>? _Int32;
        /// <summary>
        /// Defines the source generated JSON serialization contract metadata for a given type.
        /// </summary>
        public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Int32> Int32
        {
            get => _Int32 ??= Create_Int32(Options, makeReadOnly: true);
        }
        
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Int32> Create_Int32(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
        {
            global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Int32>? jsonTypeInfo = null;
            global::System.Text.Json.Serialization.JsonConverter? customConverter;
            if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::System.Int32))) != null)
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.Int32>(options, customConverter);
            }
            else
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.Int32>(options, global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.Int32Converter);
            }
        
            if (makeReadOnly)
            {
                jsonTypeInfo.MakeReadOnly();
            }
        
            return jsonTypeInfo;
        }
        
    }
}

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618

namespace JsonSerializerOptionsExample
{
    internal partial class OptionsExampleContext
    {
        
        private static readonly global::System.Text.Json.JsonEncodedText PropName_Date = global::System.Text.Json.JsonEncodedText.Encode("Date");
        private static readonly global::System.Text.Json.JsonEncodedText PropName_TemperatureCelsius = global::System.Text.Json.JsonEncodedText.Encode("TemperatureCelsius");
        private static readonly global::System.Text.Json.JsonEncodedText PropName_Summary = global::System.Text.Json.JsonEncodedText.Encode("Summary");
    }
}

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618

namespace JsonSerializerOptionsExample
{
    internal partial class OptionsExampleContext
    {
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.String>? _String;
        /// <summary>
        /// Defines the source generated JSON serialization contract metadata for a given type.
        /// </summary>
        public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.String> String
        {
            get => _String ??= Create_String(Options, makeReadOnly: true);
        }
        
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.String> Create_String(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
        {
            global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.String>? jsonTypeInfo = null;
            global::System.Text.Json.Serialization.JsonConverter? customConverter;
            if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::System.String))) != null)
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.String>(options, customConverter);
            }
            else
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.String>(options, global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.StringConverter);
            }
        
            if (makeReadOnly)
            {
                jsonTypeInfo.MakeReadOnly();
            }
        
            return jsonTypeInfo;
        }
        
    }
}

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618

namespace JsonSerializerOptionsExample
{
    internal partial class OptionsExampleContext
    {
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonSerializerOptionsExample.WeatherForecast>? _WeatherForecast;
        /// <summary>
        /// Defines the source generated JSON serialization contract metadata for a given type.
        /// </summary>
        public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonSerializerOptionsExample.WeatherForecast> WeatherForecast
        {
            get => _WeatherForecast ??= Create_WeatherForecast(Options, makeReadOnly: true);
        }
        
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonSerializerOptionsExample.WeatherForecast> Create_WeatherForecast(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
        {
            global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonSerializerOptionsExample.WeatherForecast>? jsonTypeInfo = null;
            global::System.Text.Json.Serialization.JsonConverter? customConverter;
            if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::JsonSerializerOptionsExample.WeatherForecast))) != null)
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::JsonSerializerOptionsExample.WeatherForecast>(options, customConverter);
            }
            else
            {
                global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::JsonSerializerOptionsExample.WeatherForecast> objectInfo = new global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::JsonSerializerOptionsExample.WeatherForecast>()
                {
                    ObjectCreator = static () => new global::JsonSerializerOptionsExample.WeatherForecast(),
                    ObjectWithParameterizedConstructorCreator = null,
                    PropertyMetadataInitializer = _ => WeatherForecastPropInit(options),
                    ConstructorParameterMetadataInitializer = null,
                    NumberHandling = default,
                    SerializeHandler = WeatherForecastSerializeHandler
                };
        
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateObjectInfo<global::JsonSerializerOptionsExample.WeatherForecast>(options, objectInfo);
            }
        
            if (makeReadOnly)
            {
                jsonTypeInfo.MakeReadOnly();
            }
        
            return jsonTypeInfo;
        }
        
        private static global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] WeatherForecastPropInit(global::System.Text.Json.JsonSerializerOptions options)
        {
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] properties = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[3];
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.DateTime> info0 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.DateTime>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::JsonSerializerOptionsExample.WeatherForecast),
                Converter = null,
                Getter = static (obj) => ((global::JsonSerializerOptionsExample.WeatherForecast)obj).Date,
                Setter = static (obj, value) => ((global::JsonSerializerOptionsExample.WeatherForecast)obj).Date = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "Date",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo0 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.DateTime>(options, info0);
            properties[0] = propertyInfo0;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Int32> info1 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Int32>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::JsonSerializerOptionsExample.WeatherForecast),
                Converter = null,
                Getter = static (obj) => ((global::JsonSerializerOptionsExample.WeatherForecast)obj).TemperatureCelsius,
                Setter = static (obj, value) => ((global::JsonSerializerOptionsExample.WeatherForecast)obj).TemperatureCelsius = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "TemperatureCelsius",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo1 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.Int32>(options, info1);
            properties[1] = propertyInfo1;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String> info2 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::JsonSerializerOptionsExample.WeatherForecast),
                Converter = null,
                Getter = static (obj) => ((global::JsonSerializerOptionsExample.WeatherForecast)obj).Summary!,
                Setter = static (obj, value) => ((global::JsonSerializerOptionsExample.WeatherForecast)obj).Summary = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "Summary",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo2 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.String>(options, info2);
            properties[2] = propertyInfo2;
        
            return properties;
        }
        
        // Intentionally not a static method because we create a delegate to it. Invoking delegates to instance
        // methods is almost as fast as virtual calls. Static methods need to go through a shuffle thunk.
        private void WeatherForecastSerializeHandler(global::System.Text.Json.Utf8JsonWriter writer, global::JsonSerializerOptionsExample.WeatherForecast? value)
        {
            if (value == null)
            {
                writer.WriteNullValue();
                return;
            }
        
            writer.WriteStartObject();
            writer.WriteString(PropName_Date, value.Date);
            writer.WriteNumber(PropName_TemperatureCelsius, value.TemperatureCelsius);
            writer.WriteString(PropName_Summary, value.Summary);
        
            writer.WriteEndObject();
        }
    }
}

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618

namespace BothModesNoOptions
{
    
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "7.0.8.17405")]
    internal partial class SourceGenerationContext
    {
        
        private static global::System.Text.Json.JsonSerializerOptions s_defaultOptions { get; } = new global::System.Text.Json.JsonSerializerOptions()
        {
            DefaultIgnoreCondition = global::System.Text.Json.Serialization.JsonIgnoreCondition.Never,
            IgnoreReadOnlyFields = false,
            IgnoreReadOnlyProperties = false,
            IncludeFields = false,
            WriteIndented = true,
        };
        
        private static global::BothModesNoOptions.SourceGenerationContext? s_defaultContext;
        
        /// <summary>
        /// The default <see cref="global::System.Text.Json.Serialization.JsonSerializerContext"/> associated with a default <see cref="global::System.Text.Json.JsonSerializerOptions"/> instance.
        /// </summary>
        public static global::BothModesNoOptions.SourceGenerationContext Default => s_defaultContext ??= new global::BothModesNoOptions.SourceGenerationContext(new global::System.Text.Json.JsonSerializerOptions(s_defaultOptions));
        
        /// <summary>
        /// The source-generated options associated with this context.
        /// </summary>
        protected override global::System.Text.Json.JsonSerializerOptions? GeneratedSerializerOptions { get; } = s_defaultOptions;
        
        /// <inheritdoc/>
        public SourceGenerationContext() : base(null)
        {
        }
        
        /// <inheritdoc/>
        public SourceGenerationContext(global::System.Text.Json.JsonSerializerOptions options) : base(options)
        {
        }
        
        private static global::System.Text.Json.Serialization.JsonConverter? GetRuntimeProvidedCustomConverter(global::System.Text.Json.JsonSerializerOptions options, global::System.Type type)
        {
            global::System.Collections.Generic.IList<global::System.Text.Json.Serialization.JsonConverter> converters = options.Converters;
        
            for (int i = 0; i < converters.Count; i++)
            {
                global::System.Text.Json.Serialization.JsonConverter? converter = converters[i];
        
                if (converter.CanConvert(type))
                {
                    if (converter is global::System.Text.Json.Serialization.JsonConverterFactory factory)
                    {
                        converter = factory.CreateConverter(type, options);
                        if (converter == null || converter is global::System.Text.Json.Serialization.JsonConverterFactory)
                        {
                            throw new global::System.InvalidOperationException(string.Format("The converter '{0}' cannot return null or a JsonConverterFactory instance.", factory.GetType()));
                        }
                    }
        
                    return converter;
                }
            }
        
            return null;
        }
    }
}

// <auto-generated/>
#nullable enable
#pragma warning disable CS0162 // Unreachable code
#pragma warning disable CS0164 // Unreferenced label
#pragma warning disable CS0219 // Variable assigned but never used

namespace JsonSerializerOptionsExample
{
    partial class WeatherForecast
    {
        /// <remarks>
        /// Pattern explanation:<br/>
        /// <code>
        /// ○ Match with 2 alternative expressions, atomically.<br/>
        ///     ○ Match a sequence of expressions.<br/>
        ///         ○ Match a character in the set [Aa].<br/>
        ///         ○ Match a character in the set [Bb].<br/>
        ///         ○ Match a character in the set [Cc].<br/>
        ///     ○ Match a sequence of expressions.<br/>
        ///         ○ Match a character in the set [Dd].<br/>
        ///         ○ Match a character in the set [Ee].<br/>
        ///         ○ Match a character in the set [Ff].<br/>
        /// </code>
        /// </remarks>
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "7.0.8.17405")]
        private static partial global::System.Text.RegularExpressions.Regex AbcOrDefGeneratedRegex() => global::System.Text.RegularExpressions.Generated.AbcOrDefGeneratedRegex_0.Instance;
    }
}

namespace System.Text.RegularExpressions.Generated
{
    using System;
    using System.CodeDom.Compiler;
    using System.Collections;
    using System.ComponentModel;
    using System.Globalization;
    using System.Runtime.CompilerServices;
    using System.Text.RegularExpressions;
    using System.Threading;

    /// <summary>Custom <see cref="Regex"/>-derived type for the AbcOrDefGeneratedRegex method.</summary>
    [GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "7.0.8.17405")]
    file sealed class AbcOrDefGeneratedRegex_0 : Regex
    {
        /// <summary>Cached, thread-safe singleton instance.</summary>
        internal static readonly AbcOrDefGeneratedRegex_0 Instance = new();
    
        /// <summary>Initializes the instance.</summary>
        private AbcOrDefGeneratedRegex_0()
        {
            base.pattern = "abc|def";
            base.roptions = RegexOptions.IgnoreCase;
            ValidateMatchTimeout(Utilities.s_defaultTimeout);
            base.internalMatchTimeout = Utilities.s_defaultTimeout;
            base.factory = new RunnerFactory();
            base.capsize = 1;
        }
    
        /// <summary>Provides a factory for creating <see cref="RegexRunner"/> instances to be used by methods on <see cref="Regex"/>.</summary>
        private sealed class RunnerFactory : RegexRunnerFactory
        {
            /// <summary>Creates an instance of a <see cref="RegexRunner"/> used by methods on <see cref="Regex"/>.</summary>
            protected override RegexRunner CreateInstance() => new Runner();
        
            /// <summary>Provides the runner that contains the custom logic implementing the specified regular expression.</summary>
            private sealed class Runner : RegexRunner
            {
                /// <summary>Scan the <paramref name="inputSpan"/> starting from base.runtextstart for the next match.</summary>
                /// <param name="inputSpan">The text being scanned by the regular expression.</param>
                protected override void Scan(ReadOnlySpan<char> inputSpan)
                {
                    // Search until we can't find a valid starting position, we find a match, or we reach the end of the input.
                    while (TryFindNextPossibleStartingPosition(inputSpan) &&
                           !TryMatchAtCurrentPosition(inputSpan) &&
                           base.runtextpos != inputSpan.Length)
                    {
                        base.runtextpos++;
                        if (Utilities.s_hasTimeout)
                        {
                            base.CheckTimeout();
                        }
                    }
                }
        
                /// <summary>Search <paramref name="inputSpan"/> starting from base.runtextpos for the next location a match could possibly start.</summary>
                /// <param name="inputSpan">The text being scanned by the regular expression.</param>
                /// <returns>true if a possible match was found; false if no more matches are possible.</returns>
                private bool TryFindNextPossibleStartingPosition(ReadOnlySpan<char> inputSpan)
                {
                    int pos = base.runtextpos;
                    ulong charMinusLow;
                    
                    // Any possible match is at least 3 characters.
                    if (pos <= inputSpan.Length - 3)
                    {
                        // The pattern matches a character in the set [CFcf] at index 2.
                        // Find the next occurrence. If it can't be found, there's no match.
                        ReadOnlySpan<char> span = inputSpan.Slice(pos);
                        for (int i = 0; i < span.Length - 2; i++)
                        {
                            int indexOfPos = span.Slice(i + 2).IndexOfAny("CFcf");
                            if (indexOfPos < 0)
                            {
                                goto NoMatchFound;
                            }
                            i += indexOfPos;
                            
                            if (((long)((0x9000000090000000UL << (int)(charMinusLow = (uint)span[i] - 'A')) & (charMinusLow - 64)) < 0) &&
                                ((long)((0x9000000090000000UL << (int)(charMinusLow = (uint)span[i + 1] - 'B')) & (charMinusLow - 64)) < 0))
                            {
                                base.runtextpos = pos + i;
                                return true;
                            }
                        }
                    }
                    
                    // No match found.
                    NoMatchFound:
                    base.runtextpos = inputSpan.Length;
                    return false;
                }
        
                /// <summary>Determine whether <paramref name="inputSpan"/> at base.runtextpos is a match for the regular expression.</summary>
                /// <param name="inputSpan">The text being scanned by the regular expression.</param>
                /// <returns>true if the regular expression matches at the current position; otherwise, false.</returns>
                private bool TryMatchAtCurrentPosition(ReadOnlySpan<char> inputSpan)
                {
                    int pos = base.runtextpos;
                    int matchStart = pos;
                    ReadOnlySpan<char> slice = inputSpan.Slice(pos);
                    
                    // Match with 2 alternative expressions, atomically.
                    {
                        if (slice.IsEmpty)
                        {
                            return false; // The input didn't match.
                        }
                        
                        switch (slice[0])
                        {
                            case 'A' or 'a':
                                if ((uint)slice.Length < 3 ||
                                    !slice.Slice(1).StartsWith("bc", StringComparison.OrdinalIgnoreCase)) // Match the string "bc" (ordinal case-insensitive)
                                {
                                    return false; // The input didn't match.
                                }
                                
                                pos += 3;
                                slice = inputSpan.Slice(pos);
                                break;
                                
                            case 'D' or 'd':
                                if ((uint)slice.Length < 3 ||
                                    !slice.Slice(1).StartsWith("ef", StringComparison.OrdinalIgnoreCase)) // Match the string "ef" (ordinal case-insensitive)
                                {
                                    return false; // The input didn't match.
                                }
                                
                                pos += 3;
                                slice = inputSpan.Slice(pos);
                                break;
                                
                            default:
                                return false; // The input didn't match.
                        }
                    }
                    
                    // The input matched.
                    base.runtextpos = pos;
                    base.Capture(0, matchStart, pos);
                    return true;
                }
            }
        }

    }
    
    /// <summary>Helper methods used by generated <see cref="Regex"/>-derived implementations.</summary>
    [GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "7.0.8.17405")]
    file static class Utilities
    {
        /// <summary>Default timeout value set in <see cref="AppContext"/>, or <see cref="Regex.InfiniteMatchTimeout"/> if none was set.</summary>
        internal static readonly TimeSpan s_defaultTimeout = AppContext.GetData("REGEX_DEFAULT_MATCH_TIMEOUT") is TimeSpan timeout ? timeout : Regex.InfiniteMatchTimeout;
        
        /// <summary>Whether <see cref="s_defaultTimeout"/> is non-infinite.</summary>
        internal static readonly bool s_hasTimeout = s_defaultTimeout != Timeout.InfiniteTimeSpan;
    }
}

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/System.Text.Json

RSCG – RSCG_TimeBombComment

 
 

name RSCG_TimeBombComment
nuget https://www.nuget.org/packages/RSCG_TimeBombComment/
link http://msprogrammer.serviciipeweb.ro/category/roslyn/
author Andrei Ignat

This will generate an error from the comment after a certain date

 

This is how you can use RSCG_TimeBombComment .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">
	<PropertyGroup>
		<OutputType>Exe</OutputType>
		<TargetFramework>net7.0</TargetFramework>
	</PropertyGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
	<ItemGroup>
		<PackageReference Include="RSCG_TimeBombComment" Version="2023.5.9.2110" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
	</ItemGroup>
</Project>


The code that you will use is


namespace Console_TimeBombComment;
internal partial class TestClass
{
    [Obsolete("this will be obsolete",TB_20230508)]
    public int DataObsolete()
    {
        return 5;
    }

    public int CommentsWithErrors()
    {
        //JFD: test
        //TB: 2021-09-13 this is a comment transformed into an error
        //TB: and this is a warning
        //TB: 2050-12-30 and this should not appear yet
        return 5;
    }
}


 

The code that is generated is


namespace Console_TimeBombComment {
    partial class TestClass { 
        const bool TB_20230508 = true;
    }
}

                

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/RSCG_TimeBombComment

RSCG – ThisAssembly

RSCG – ThisAssembly
 
 

name ThisAssembly
nuget https://www.nuget.org/packages/ThisAssembly
link https://www.clarius.org/ThisAssembly/
author Daniel Cazzulino

The ThisAssembly.Info allows you access to the Assembly Information as constants, instead of going to reflection each time.

I found useful to see the assembly version right away in any project that I have.

 

This is how you can use ThisAssembly .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">
	<PropertyGroup>
		<OutputType>Exe</OutputType>
		<TargetFramework>netcoreapp7.0</TargetFramework>
	</PropertyGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
	<PropertyGroup>
		<Version>2023.5.7.800</Version>
	</PropertyGroup>
	<ItemGroup>
		<PackageReference Include="ThisAssembly" Version="1.2.14" OutputItemType="Analyzer" ReferenceOutputAssembly="false">
			<PrivateAssets>all</PrivateAssets>
			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
		</PackageReference>
	</ItemGroup>
</Project>


The code that you will use is


var strVersion = ThisAssembly.Info.Version;
System.Console.WriteLine(strVersion);


 

The code that is generated is

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;

/// <summary>
/// Provides access to the current assembly information as pure constants, 
///  without requiring reflection.
/// </summary>
partial class ThisAssembly
{
    /// <summary>
    /// Gets the AssemblyInfo attributes.
    /// </summary>
    [GeneratedCode("ThisAssembly.AssemblyInfo", "1.2.14")]
    [CompilerGenerated]
    public static partial class Info
    {
        public const string Company = @"RSCG_Version";

        public const string Configuration = @"Debug";

        public const string FileVersion = @"2023.5.7.800";

        public const string InformationalVersion = @"2023.5.7.800";

        public const string Product = @"RSCG_Version";

        public const string Title = @"RSCG_Version";

        public const string Version = @"2023.5.7.800";

    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;

partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Branch = @"[pending build]";
    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;

partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Commit = @"[pending build]";
    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;

partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Root = @"[pending build]";
    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;

partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Sha = @"[pending build]";
    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;

partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Url = @"[pending build]";
    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;

/// <summary>
/// Provides access to the current assembly information as pure constants, 
///  without requiring reflection.
/// </summary>
partial class ThisAssembly
{
    /// <summary>
    /// Gets the assembly metadata.
    /// </summary>
    [GeneratedCode("ThisAssembly.Metadata", "1.2.14")]
    [CompilerGenerated]
    public static partial class Metadata
    {
    }
}
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;

/// <summary>
/// Provides access to the current assembly information as pure constants, 
///  without requiring reflection.
/// </summary>
partial class ThisAssembly
{
    /// <summary>
    /// Gets the project properties.
    /// </summary>
    [GeneratedCode("ThisAssembly.Project", "1.2.14")]
    [CompilerGenerated]
    public static partial class Project
    {
        /// <summary>AssemblyName = RSCG_Version</summary>
        public const string AssemblyName = @"RSCG_Version";

        /// <summary>RootNamespace = RSCG_Version</summary>
        public const string RootNamespace = @"RSCG_Version";

        /// <summary>TargetFrameworkIdentifier = .NETCoreApp</summary>
        public const string TargetFrameworkIdentifier = @".NETCoreApp";

        /// <summary>TargetFrameworkMoniker = .NETCoreApp,Version=v7.0</summary>
        public const string TargetFrameworkMoniker = @".NETCoreApp,Version=v7.0";

        /// <summary>TargetFrameworkVersion = v7.0</summary>
        public const string TargetFrameworkVersion = @"v7.0";

    }
}
using System;
using System.IO;
using System.Linq;
using System.Reflection;

static class EmbeddedResource
{
    static readonly string baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "";

    public static string GetContent(string relativePath)
    {
        using var stream = GetStream(relativePath);
        using var reader = new StreamReader(stream);
        return reader.ReadToEnd();
    }

    public static byte[] GetBytes(string relativePath)
    {
        using var stream = GetStream(relativePath);
        var bytes = new byte[stream.Length];
        stream.Read(bytes, 0, bytes.Length);
        return bytes;
    }

    public static Stream GetStream(string relativePath)
    {
        var filePath = Path.Combine(baseDir, Path.GetFileName(relativePath));
        if (File.Exists(filePath))
            return File.OpenRead(filePath);

        var baseName = Assembly.GetExecutingAssembly().GetName().Name;
        var resourceName = relativePath
            .TrimStart('.')
            .Replace('/', '.')
            .Replace('\\', '.');

        var manifestResourceName = Assembly.GetExecutingAssembly()
            .GetManifestResourceNames().FirstOrDefault(x => x.EndsWith(resourceName));

        if (string.IsNullOrEmpty(manifestResourceName))
            throw new InvalidOperationException($"Did not find required resource ending in '{resourceName}' in assembly '{baseName}'.");

        return
            Assembly.GetExecutingAssembly().GetManifestResourceStream(manifestResourceName) ??
            throw new InvalidOperationException($"Did not find required resource '{manifestResourceName}' in assembly '{baseName}'.");
    }
}
using System.Collections.Concurrent;
using System.Resources;
using System.Runtime.CompilerServices;

/// <summary>
/// Provides access to the current assembly information as pure constants, 
///  without requiring reflection.
/// </summary>
partial class ThisAssembly
{
    /// <summary>
    /// Access the strings provided by resource files in the project.
    /// </summary>
    [CompilerGenerated]
    public static partial class Strings
    {
        static ConcurrentDictionary<string, ResourceManager> resourceManagers = new ConcurrentDictionary<string, ResourceManager>();

        static ResourceManager GetResourceManager(string resourceName)
            => resourceManagers.GetOrAdd(resourceName, name => new ResourceManager(name, typeof(Strings).Assembly));
    }
}

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/ThisAssembly

RSCG–ISourceGenerator porting to IIncrementalGenerator in 3 steps

Roslyn Source Code Generators (RSCG) have deprecated the ISourceGenerator  (roslyn/source-generators.md at main · dotnet/roslyn · GitHub )   vs the new interface IIncrementalGenerator , roslyn/incremental-generators.md at main · dotnet/roslyn · GitHub . That because of the idea of speed of generating code – and the idea of not generating twice the same code.

How is the implementation of IIncrementalGenerator , when you have already an ISourceGenerator  ?

I have moved the https://github.com/ignatandrei/rsCG_timeBombComment/ ( the generates code to transform comments / obsolete attribute as errors , after a time) and  https://github.com/ignatandrei/SkinnyControllersGenerator/ those are my findings

  1. Read the theory from https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.md .  The ISourceGenerator was simpler to understand. After you read you can see how  the IIncrementalGenerator makes sense for increasing performance of RSCG.
  2. The code from ISourceGenerator  could be copy and paste to IIncrementalGenerator . The code from ISourceGenerator.Initialize belongs now to context.SyntaxProvider.CreateSyntaxProvider –> predicate , where the code that obtain the datas is written after this
  3. The real code that generates the new source code belong to context.RegisterSourceOutput

 

There are some problems

  1. Register a diagnostic occurs later  – could be fixed with Analyzers – see Incremental Roslyn Source Generators In .NET 6: Better Experience Through Roslyn Analyzers & Code Fixes – Part 2 – Thinktecture AG
  2. The additional files also occurs later – could be fixed by having a prefix in the file name in the order to not load all files content

Overall , this is a nicer way to wrote code ( although the learning curve is bigger). You can see the result at file RSCG_TimeBombComment\src\RSCG_TimeBombComment\RSCG_TimeBombComment\GenerateFromComments.cs vs RSCG_TimeBombComment\src\RSCG_TimeBombComment\RSCG_TimeBombComment\GenerateFromCommentsIncremental.cs from repo https://github.com/ignatandrei/rsCG_timeBombComment/

If you want to see more RSCG with the new method, keep an eye to https://ignatandrei.github.io/RSCG_Examples/v2/

 

 

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.