More than100 examples of RSCG

I am deeply into Roslyn Source Code Generators. I like when code generates code . So I have created ones and make inventory of others  . You can find the examples here by date : https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG  and by category https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples 

I have started when they appeared, with ISourceGenerator and now I am fond , even if the interface

IIncrementalGenerator https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.iincrementalgenerator?view=roslyn-dotnet-4.7.0 adds some learning curve.

Some thoughts:

  1. Being code ( even generated) has , obvious, bugs. Can be improved
  2. Microsoft is pushing those –  for the moments, are 12 : List of RSCG | RSCG Examples (ignatandrei.github.io) . However, for AOT , seems to be the direction
  3. Some are just glorified interpretors – for example, 103 – HangfireRecurringJob | RSCG Examples (ignatandrei.github.io) – translates an attribute to code. But also does a Mapper
  4. There are many ways to do same thing – see mapper category again at 105 RSCG by category | RSCG Examples (ignatandrei.github.io)
  5. To see the generated files put into the .csproj

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

Aspire & Intro to GitHub Copilot

Azi , la 19:30

Prezentare 1: Aspire – running multiple services
Descriere: Utilizare Aspire pentru vizualizare multiple servicii, open telemetry, frontend , backend, containere
Prezentator: Andrei Ignat, http://msprogrammer.serviciipeweb.ro/

Prezentare 2: Intro to GitHub Copilot
Descriere : Voi prezenta:
– la ce am folosit eu Copilot
– ⁠ce e nou în Copilot Chat
– ⁠vom încerca să facem un joc de la zero – doar cu cod generat pe baza unei prezentări de la MS Build 2023 –
Prezentator : Julian (Iulian) Atanasoae , https://www.linkedin.com/in/julianatanasoae/

Va astept la https://meet.google.com/pmm-oeyc-dmy

RSCG – NetAutomaticInterface

RSCG – NetAutomaticInterface
 
 

name NetAutomaticInterface
nuget https://www.nuget.org/packages/AutomaticInterface/
link https://github.com/codecentric/net_automatic_interface
author codecentric AG

GEnerating interface from class

 

This is how you can use NetAutomaticInterface .

The code that you start with is


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

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

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

	<ItemGroup>
	  <PackageReference Include="AutomaticInterface" Version="2.1.0" OutputItemType="Analyzer" >
	    <PrivateAssets>all</PrivateAssets>
	    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
	  </PackageReference>
	</ItemGroup>
</Project>


The code that you will use is


// See https://aka.ms/new-console-template for more information
using Class2Interface;

Console.WriteLine("Hello, World!");
IPerson person=new Person();
person.FirstName="Andrei";
person.LastName="Ignat";
Console.WriteLine(person.FullName());


[AttributeUsage(AttributeTargets.Class)]
public class GenerateAutomaticInterfaceAttribute : Attribute
{
    public GenerateAutomaticInterfaceAttribute(string namespaceName = "") { }
}


namespace Class2Interface;
[GenerateAutomaticInterface("Class2Interface")]
internal class Person:IPerson
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Name
    {
        get
        {
            return $"{FirstName} {LastName}";
        }
    }
    public string FullName()=>$"{FirstName} {LastName}";
}


 

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;

namespace Class2Interface
{
    [GeneratedCode("AutomaticInterface", "")]
    public partial interface IPerson
    {
        /// <inheritdoc />
        int ID { get; set; }
        
        /// <inheritdoc />
        string FirstName { get; set; }
        
        /// <inheritdoc />
        string LastName { get; set; }
        
        /// <inheritdoc />
        string Name { get; }
        
        /// <inheritdoc />
        string FullName();
        
    }
}

Code and pdf at

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

RSCG – WhatIAmDoing

RSCG – WhatIAmDoing
 
 

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

Intercept any method in any project

 

This is how you can use WhatIAmDoing .

The code that you start with is


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

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

	<ItemGroup>
		<!-- <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" /> -->
		<PackageReference Include="RSCG_WhatIAmDoing" Version="8.2024.10201.735" />
		<PackageReference Include="RSCG_WhatIAmDoing_Common" Version="8.2024.10201.735" />
	</ItemGroup>

	<PropertyGroup>

		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
		<InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);RSCG_InterceptorTemplate</InterceptorsPreviewNamespaces>
	</PropertyGroup>

</Project>


The code that you will use is


using RSCG_WhatIAmDoing_Common;

Console.WriteLine("Hello, World!");
var data = CachingData.Methods().ToArray();

foreach (var item in data)
{
    Console.WriteLine($"Method {item.typeAndMethodData.MethodName} from class {item.typeAndMethodData.TypeOfClass} Time: {item.StartedAtDate} state {item.State} ");
    Console.WriteLine($"  =>Arguments: {item.ArgumentsAsString()}");
    if ((item.State & AccumulatedStateMethod.HasResult) == AccumulatedStateMethod.HasResult)
    {
        Console.WriteLine($"  =>Result: {item.Result}");
    }

}



using RSCG_WhatIAmDoing;
using RSCG_WhatIAmDoing_Common;

namespace WIADDemo;
//[ExposeClass(typeof(Encoding), nameof(Encoding.EncodingName))]
[InterceptStatic("System.Console.*")] // regex
internal class InterceptorMethodStatic : InterceptorMethodStaticBase, IInterceptorMethodStatic
{

}

 

The code that is generated is

#pragma warning disable CS1591 
#pragma warning disable CS9113
namespace System.Runtime.CompilerServices{
[AttributeUsage(AttributeTargets.Method,AllowMultiple =true)]
file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute
{
}
}//end namespace

namespace RSCG_InterceptorTemplate{
static partial class SimpleIntercept
{


//replace code:Console.WriteLine("Hello, World!");
//replace code:123456789!123456789!123456789!12345
[System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\WIAD\src\WIADDemo\WIADDemo\Program.cs", 3, 9)]
    
//[System.Diagnostics.DebuggerStepThrough()]
public static  void Intercept__WriteLine_0 (  string? value )  
{

System.Collections.Generic.Dictionary<string,string?> valValues = new (){


};//end valValues

System.Collections.Generic.Dictionary<string,string?> stringValues = new() {


                { "value", value  ?.ToString() } ,
            };//end stringValues

        System.Collections.Generic.Dictionary<string,string?>
            expValues = new() {

            };//end exposeValues


        var x=WIADDemo.InterceptorMethodStatic .InterceptStaticMethodBefore(
$$$""""
    {"IsVoid":true,"Tag":"","MethodName":"WriteLine","TypeOfClass":"System.Console"}
""""
            ,valValues , stringValues , expValues
)
; 


                try{

                 System.Console.WriteLine(value);

                WIADDemo.InterceptorMethodStatic .InterceptMethodAfterWithoutResult(x);
                
                }

            
        
            catch(System.Exception ex){
                WIADDemo.InterceptorMethodStatic .InterceptMethodException(x,ex);
                throw;
            }
            finally{
                WIADDemo.InterceptorMethodStatic .InterceptMethodFinally(x);
            }
        
}
                

}//end class

}//namespace RSCG_InterceptorTemplate


#pragma warning disable CS1591 
#pragma warning disable CS9113
namespace System.Runtime.CompilerServices{
[AttributeUsage(AttributeTargets.Method,AllowMultiple =true)]
file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute
{
}
}//end namespace

namespace RSCG_InterceptorTemplate{
static partial class SimpleIntercept
{


//replace code:    Console.WriteLine($"Method {item.typeAndMethodData.MethodName} from class {item.typeAndMethodData.TypeOfClass} Time: {item.StartedAtDate} state {item.State} ");
//replace code:123456789!123456789!123456789!123456789!123456789!123456789!123456789!123456789!123456789!123456789!123456789!123456789!123456789!123456789!123456789!123456789!1234
[System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\WIAD\src\WIADDemo\WIADDemo\Program.cs", 8, 13)]
    
//[System.Diagnostics.DebuggerStepThrough()]
public static  void Intercept__WriteLine_1 (  string? value )  
{

System.Collections.Generic.Dictionary<string,string?> valValues = new (){


};//end valValues

System.Collections.Generic.Dictionary<string,string?> stringValues = new() {


                { "value", value  ?.ToString() } ,
            };//end stringValues

        System.Collections.Generic.Dictionary<string,string?>
            expValues = new() {

            };//end exposeValues


        var x=WIADDemo.InterceptorMethodStatic .InterceptStaticMethodBefore(
$$$""""
    {"IsVoid":true,"Tag":"","MethodName":"WriteLine","TypeOfClass":"System.Console"}
""""
            ,valValues , stringValues , expValues
)
; 


                try{

                 System.Console.WriteLine(value);

                WIADDemo.InterceptorMethodStatic .InterceptMethodAfterWithoutResult(x);
                
                }

            
        
            catch(System.Exception ex){
                WIADDemo.InterceptorMethodStatic .InterceptMethodException(x,ex);
                throw;
            }
            finally{
                WIADDemo.InterceptorMethodStatic .InterceptMethodFinally(x);
            }
        
}
                

}//end class

}//namespace RSCG_InterceptorTemplate


#pragma warning disable CS1591 
#pragma warning disable CS9113
namespace System.Runtime.CompilerServices{
[AttributeUsage(AttributeTargets.Method,AllowMultiple =true)]
file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute
{
}
}//end namespace

namespace RSCG_InterceptorTemplate{
static partial class SimpleIntercept
{


//replace code:    Console.WriteLine($"  =>Arguments: {item.ArgumentsAsString()}");
//replace code:123456789!123456789!123456789!123456789!123456789!123456789!12345678
[System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\WIAD\src\WIADDemo\WIADDemo\Program.cs", 9, 13)]
    
//[System.Diagnostics.DebuggerStepThrough()]
public static  void Intercept__WriteLine_2 (  string? value )  
{

System.Collections.Generic.Dictionary<string,string?> valValues = new (){


};//end valValues

System.Collections.Generic.Dictionary<string,string?> stringValues = new() {


                { "value", value  ?.ToString() } ,
            };//end stringValues

        System.Collections.Generic.Dictionary<string,string?>
            expValues = new() {

            };//end exposeValues


        var x=WIADDemo.InterceptorMethodStatic .InterceptStaticMethodBefore(
$$$""""
    {"IsVoid":true,"Tag":"","MethodName":"WriteLine","TypeOfClass":"System.Console"}
""""
            ,valValues , stringValues , expValues
)
; 


                try{

                 System.Console.WriteLine(value);

                WIADDemo.InterceptorMethodStatic .InterceptMethodAfterWithoutResult(x);
                
                }

            
        
            catch(System.Exception ex){
                WIADDemo.InterceptorMethodStatic .InterceptMethodException(x,ex);
                throw;
            }
            finally{
                WIADDemo.InterceptorMethodStatic .InterceptMethodFinally(x);
            }
        
}
                

}//end class

}//namespace RSCG_InterceptorTemplate


#pragma warning disable CS1591 
#pragma warning disable CS9113
namespace System.Runtime.CompilerServices{
[AttributeUsage(AttributeTargets.Method,AllowMultiple =true)]
file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute
{
}
}//end namespace

namespace RSCG_InterceptorTemplate{
static partial class SimpleIntercept
{


//replace code:        Console.WriteLine($"  =>Result: {item.Result}");
//replace code:123456789!123456789!123456789!123456789!123456789!123456
[System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\WIAD\src\WIADDemo\WIADDemo\Program.cs", 12, 17)]
    
//[System.Diagnostics.DebuggerStepThrough()]
public static  void Intercept__WriteLine_3 (  string? value )  
{

System.Collections.Generic.Dictionary<string,string?> valValues = new (){


};//end valValues

System.Collections.Generic.Dictionary<string,string?> stringValues = new() {


                { "value", value  ?.ToString() } ,
            };//end stringValues

        System.Collections.Generic.Dictionary<string,string?>
            expValues = new() {

            };//end exposeValues


        var x=WIADDemo.InterceptorMethodStatic .InterceptStaticMethodBefore(
$$$""""
    {"IsVoid":true,"Tag":"","MethodName":"WriteLine","TypeOfClass":"System.Console"}
""""
            ,valValues , stringValues , expValues
)
; 


                try{

                 System.Console.WriteLine(value);

                WIADDemo.InterceptorMethodStatic .InterceptMethodAfterWithoutResult(x);
                
                }

            
        
            catch(System.Exception ex){
                WIADDemo.InterceptorMethodStatic .InterceptMethodException(x,ex);
                throw;
            }
            finally{
                WIADDemo.InterceptorMethodStatic .InterceptMethodFinally(x);
            }
        
}
                

}//end class

}//namespace RSCG_InterceptorTemplate


Code and pdf at

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

RSCG – NotNotAppSettings

RSCG – NotNotAppSettings
 
 

name NotNotAppSettings
nuget https://www.nuget.org/packages/NotNot.AppSettings/
link https://github.com/jasonswearingen/NotNot.AppSettings/
author jasonswearingen

Application Settings to strongly typed classes. Generate also from AppSettings development

 

This is how you can use NotNotAppSettings .

The code that you start with is


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

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <InvariantGlobalization>true</InvariantGlobalization>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.1" />
    <PackageReference Include="NotNot.AppSettings" Version="1.0.0" OutputItemType="Analyzer" ReferenceOutputAssembly="true" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
  </ItemGroup>

  <ItemGroup>
    <AdditionalFiles Update="appsettings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </AdditionalFiles>
  </ItemGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
</Project>


The code that you will use is


var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<TestAppSettings.AppSettingsGen.IAppSettingsBinder, TestAppSettings.AppSettingsGen.AppSettingsBinder>();

var app = builder.Build();

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

app.UseHttpsRedirection();

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

var appSettings = app.Services.GetRequiredService<TestAppSettings.AppSettingsGen.IAppSettingsBinder>().AppSettings;
Console.WriteLine(appSettings.AppName);

app.MapGet("/weatherforecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();

app.Run();

internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}


 

The code that is generated is


/** 
 * This file is generated by the NotNot.AppSettings nuget package.
 * Do not edit this file directly, instead edit the appsettings.json files and rebuild the project.
**/
using System;
using System.Runtime.CompilerServices;
namespace TestAppSettings.AppSettingsGen;

[CompilerGenerated]
public partial class AppSettings {
   public TestAppSettings.AppSettingsGen._AppSettings.Logging? Logging{get; set;}
   public string? AllowedHosts{get; set;}
   public string? AppName{get; set;}

}


/** 
 * This file is generated by the NotNot.AppSettings nuget package.
 * Do not edit this file directly, instead edit the appsettings.json files and rebuild the project.
**/
using System;
using System.Runtime.CompilerServices;
namespace TestAppSettings.AppSettingsGen._AppSettings;

[CompilerGenerated]
public partial class Logging {
   public TestAppSettings.AppSettingsGen._AppSettings._Logging.LogLevel? LogLevel{get; set;}

}


/** 
 * This file is generated by the NotNot.AppSettings nuget package.
 * Do not edit this file directly, instead edit the appsettings.json files and rebuild the project.
**/
using System;
using System.Runtime.CompilerServices;
namespace TestAppSettings.AppSettingsGen._AppSettings._Logging;

[CompilerGenerated]
public partial class LogLevel {
   public string? Default{get; set;}
   public string? Microsoft_AspNetCore{get; set;}

}


/** 
 * This file is generated by the NotNot.AppSettings nuget package.
 * Do not edit this file directly, instead edit the appsettings.json files and rebuild the project.
**/

using Microsoft.Extensions.Configuration;
namespace TestAppSettings.AppSettingsGen;


/// <summary>
/// Strongly typed AppSettings.json, recreated every build. 
/// <para>You can use this directly, extend it (it's a partial class), 
/// or get a populated instance of it via the <see cref="AppSettingsBinder"/> DI service</para>
/// </summary>
public partial class AppSettings
{
}

/// <summary>
/// a DI service that contains a strongly-typed copy of your appsettings.json
/// <para><strong>DI Usage:</strong></para>
/// <para><c>builder.Services.AddSingleton&lt;IAppSettingsBinder, AppSettingsBinder&gt;();</c></para>
/// <para><c>var app = builder.Build();</c></para>
///  <para><c>var appSettings = app.Services.GetRequiredService&lt;IAppSettingsBinder&gt;().AppSettings;</c></para>
/// <para><strong>Non-DI Usage:</strong></para>
/// <para><c>var appSettings = AppSettingsBinder.LoadDirect();</c></para>
/// </summary>
public partial class AppSettingsBinder : IAppSettingsBinder
{
   public AppSettings AppSettings { get; protected set; }

   public AppSettingsBinder(IConfiguration _config)
   {
      AppSettings = new AppSettings();

      //automatically reads and binds to config file
      _config.Bind(AppSettings);
   }

   /// <summary>
   /// Manually construct an AppSettings from your appsettings.json files.
   /// <para>NOTE: This method is provided for non-DI users.  If you use DI, don't use this method.  Instead just register this class as a service.</para>
   /// </summary>
   /// <param name="appSettingsLocation">folder where to search for appsettings.json.  defaults to current app folder.</param>
   /// <param name="appSettingsFileNames">lets you override the files to load up.  defaults to 'appsettings.json' and 'appsettings.{DOTNET_ENVIRONMENT}.json'</param>
   /// <param name="throwIfFilesMissing">default is to silently ignore if any of the .json files are missing.</param>
   /// <returns>your strongly typed appsettings with values from your .json loaded in</returns>
   public static AppSettings LoadDirect(string? appSettingsLocation = null,IEnumerable<string>? appSettingsFileNames=null,bool throwIfFilesMissing=false )
   {      
      //pick what .json files to load
      if (appSettingsFileNames is null)
      {
         //figure out what env
         var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
         env ??= Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
         env ??= Environment.GetEnvironmentVariable("ENVIRONMENT");
         //env ??= "Development"; //default to "Development
         if (env is null)
         {
            appSettingsFileNames = new[] { "appsettings.json" };
         }
         else
         {
            appSettingsFileNames = new[] { "appsettings.json", $"appsettings.{env}.json" };
         }
      }

      //build a config from the specified files
      var builder = new ConfigurationBuilder();
      if (appSettingsLocation != null)
      {
         builder.SetBasePath(appSettingsLocation);
      }
      var optional = !throwIfFilesMissing;
      foreach (var fileName in appSettingsFileNames)
      {         
         builder.AddJsonFile(fileName, optional: optional, reloadOnChange: false); // Add appsettings.json
      }
      IConfigurationRoot configuration = builder.Build();

      //now finally get the appsettings we care about
      var binder = new AppSettingsBinder(configuration);
      return binder.AppSettings;
   }
}

/// <summary>
/// a DI service that contains a strongly-typed copy of your appsettings.json
/// <para><strong>DI Usage:</strong></para>
/// <para><c>builder.Services.AddSingleton&lt;IAppSettingsBinder, AppSettingsBinder&gt;();</c></para>
/// <para><c>var app = builder.Build();</c></para>
///  <para><c>var appSettings = app.Services.GetRequiredService&lt;IAppSettingsBinder&gt;().AppSettings;</c></para>
/// <para><strong>Non-DI Usage:</strong></para>
/// <para><c>var appSettings = AppSettingsBinder.LoadDirect();</c></para>
/// </summary>
public interface IAppSettingsBinder
{
   public AppSettings AppSettings { get; }
}

Code and pdf at

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

RSCG – Weave

RSCG – Weave
 
 

name Weave
nuget https://www.nuget.org/packages/Weave/
link https://github.com/otac0n/Weave
author John Gietzen

Scriban like generator

 

This is how you can use Weave .

The code that you start with is


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

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

	<ItemGroup>
	  <None Remove="MyDataT.weave" />
	</ItemGroup>
	<ItemGroup>
		<PackageReference Include="Weave" Version="2.1.0">
			<PrivateAssets>all</PrivateAssets>
			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
		</PackageReference>
	</ItemGroup>
	<ItemGroup>
	  <WeaveTemplate Include="MyDataT.weave">
	    
	  </WeaveTemplate>
	</ItemGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>

</Project>


The code that you will use is


using WeaveDemo;

Person p = new()
{
FirstName = "Andrei", LastName = "Ignat" 
};


MyProject.Templates.RenderFizzBuzz(p, Console.Out);

StringWriter sw = new();
MyProject.Templates.RenderFizzBuzz(p, sw);
Console.WriteLine("---------------------------");
Console.WriteLine(sw.ToString());




namespace WeaveDemo;
internal class Person
{
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
    public string FullName() => $"{FirstName} {LastName}";
}


 

The code that is generated is

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

namespace
    #line 1 "..\..\..\MyDataT.weave"
           MyProject
    #line default
{
    using System;
    using System.IO;

    partial class
    Templates
    {
        [System.CodeDom.Compiler.GeneratedCode("Weave", "2.1.0.0")]
        public
        static void
        #line 2 "..\..\..\MyDataT.weave"
            RenderFizzBuzz
        #line default
            (
            #line 3 "..\..\..\MyDataT.weave"
       WeaveDemo.Person
            #line default
            model, TextWriter writer, string indentation = null)
        {
            var __originalIndentation = indentation = indentation ?? string.Empty;
            writer.Write(indentation);
            writer.Write("I will write p.FullName();");
            writer.WriteLine();
            writer.WriteLine();
            writer.Write(indentation);
            writer.Write(
                #line 7 "..\..\..\MyDataT.weave"
    model.FullName() 
                #line default
                );
            writer.WriteLine();
        }
    }
}

Code and pdf at

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

RSCG – HangfireRecurringJob

RSCG – HangfireRecurringJob
 
 

name HangfireRecurringJob
nuget https://www.nuget.org/packages/IeuanWalker.Hangfire.RecurringJob/
link https://github.com/IeuanWalker/Hangfire.RecurringJob
author Ieuan Walker

Generating recurring jobs for Hangfire from class attribute

 

This is how you can use HangfireRecurringJob .

The code that you start with is


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

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <InvariantGlobalization>true</InvariantGlobalization>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Hangfire.AspNetCore" Version="1.8.9" />
    <PackageReference Include="Hangfire.Core" Version="1.8.9" />
    <PackageReference Include="Hangfire.InMemory" Version="0.7.0" />
    <!--<PackageReference Include="Hangfire.MemoryStorage" Version="1.8.0" />-->
    <PackageReference Include="Hangfire.SqlServer" Version="1.8.9" />
    <PackageReference Include="IeuanWalker.Hangfire.RecurringJob" Version="1.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.1" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
  </ItemGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
</Project>


The code that you will use is


using IeuanWalker.Hangfire.RecurringJob.Attributes;

namespace HangFireRec;
[RecurringJob("*/1 * * * *")]
public class MyNewJob
{
    public async Task Execute()
    {
       await Task.Delay(1000);
        Console.WriteLine("Hello from recurring job hangfire");
    }
}



using Hangfire;
//using Hangfire.MemoryStorage;
using HangFireRec;
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddHangfire(it =>
{
    it.UseInMemoryStorage();
    
});
builder.Services.AddHangfireServer(opt =>
{
    //config.UseMemoryStorage();
});
//GlobalConfiguration.Configuration.UseInMemoryStorage();
var app = builder.Build();

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

app.UseHangfireDashboard();
//app.UseHangfireServer();

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();
BackgroundJob.Enqueue(() =>Console.WriteLine("Hello from hangfire"));
RecurringJob.AddOrUpdate(() => Console.WriteLine("Hello from hangfire"), Cron.Minutely());
app.AddRecurringJobsFromHangFireRec();
app.Run();

internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}


 

The code that is generated is

namespace HangFireRec;

// <auto-generated/>

using Hangfire;
using Microsoft.AspNetCore.Builder;

public static class RecurringJobRegistrationExtensions
{
	public static IApplicationBuilder AddRecurringJobsFromHangFireRec(this IApplicationBuilder app)
	{
		RecurringJob.AddOrUpdate<HangFireRec.MyNewJob>("MyNewJob", "default", x => x.Execute(), "*/1 * * * *", new RecurringJobOptions
		{
			TimeZone = TimeZoneInfo.FindSystemTimeZoneById("UTC")
		});

		return app;
	}
}

Code and pdf at

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

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.