Category: .NET Core

RSCG – N.SourceGenerators.UnionTypes

RSCG – N.SourceGenerators.UnionTypes
 
 

name N.SourceGenerators.UnionTypes
nuget https://www.nuget.org/packages/N.SourceGenerators.UnionTypes/
link https://github.com/Ne4to/N.SourceGenerators.UnionTypes
author Alexey Sosnin

Generating different union types

 

This is how you can use N.SourceGenerators.UnionTypes .

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="N.SourceGenerators.UnionTypes" Version="0.26.0" />
  </ItemGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
</Project>


The code that you will use is


using UnionTypesDemo;

Console.WriteLine("Save or not");
var data = SaveToDatabase.Save(0);
Console.WriteLine(data.IsValidationError);
data = SaveToDatabase.Save(1);
Console.WriteLine(data.IsSuccess);



using N.SourceGenerators.UnionTypes;
namespace UnionTypesDemo;
public record Success(int Value);
public record ValidationError(string Message);

[UnionType(typeof(Success))]
[UnionType(typeof(ValidationError))]
public partial class ResultSave
{
}





namespace UnionTypesDemo;

public class SaveToDatabase
{
    public static ResultSave Save(int i)
    {
        if(i ==0)
        {
            return new ValidationError(" cannot save 0");
        }
        return new Success(i);
    }
}




 

The code that is generated is

// <auto-generated>
//   This code was generated by https://github.com/Ne4to/N.SourceGenerators.UnionTypes
//   Feel free to open an issue
// </auto-generated>
#nullable enable
using System;
using System.Runtime.CompilerServices;

namespace N.SourceGenerators.UnionTypes
{
    [AttributeUsage(AttributeTargets.GenericParameter, Inherited = false, AllowMultiple = false)]
    internal sealed class GenericUnionTypeAttribute : Attribute
    {
        public string? Alias { get; set; }
        public bool AllowNull { get; set; }
        public object? TypeDiscriminator { get; set; }
    }
}
// <auto-generated>
//   This code was generated by https://github.com/Ne4to/N.SourceGenerators.UnionTypes
//   Feel free to open an issue
// </auto-generated>
#nullable enable
using System;
using System.Runtime.CompilerServices;

namespace N.SourceGenerators.UnionTypes
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
    internal sealed class JsonPolymorphicUnionAttribute : Attribute
    {
        public string? TypeDiscriminatorPropertyName { get; set; }
    }
}
// <auto-generated>
//   This code was generated by https://github.com/Ne4to/N.SourceGenerators.UnionTypes
//   Feel free to open an issue
// </auto-generated>
#pragma warning disable
#nullable enable
namespace UnionTypesDemo
{
    partial class ResultSave : System.IEquatable<ResultSave>
    {
        private readonly int _variantId;
        private const int SuccessId = 1;
        private readonly global::UnionTypesDemo.Success _success;
        public bool IsSuccess => _variantId == SuccessId;

        public global::UnionTypesDemo.Success AsSuccess
        {
            get
            {
                if (_variantId == SuccessId)
                    return _success;
                throw new System.InvalidOperationException($"Unable convert to Success. Inner value is {ValueAlias} not Success.");
            }
        }

        public ResultSave(global::UnionTypesDemo.Success success)
        {
            System.ArgumentNullException.ThrowIfNull(success);
            _variantId = SuccessId;
            _success = success;
        }

        public static implicit operator ResultSave(global::UnionTypesDemo.Success success) => new ResultSave(success);
        public static explicit operator global::UnionTypesDemo.Success(ResultSave value)
        {
            if (value._variantId == SuccessId)
                return value._success;
            throw new System.InvalidOperationException($"Unable convert to Success. Inner value is {value.ValueAlias} not Success.");
        }

        public bool TryGetSuccess([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out global::UnionTypesDemo.Success value)
        {
            if (_variantId == SuccessId)
            {
                value = _success;
                return true;
            }
            else
            {
                value = default;
                return false;
            }
        }

        private const int ValidationErrorId = 2;
        private readonly global::UnionTypesDemo.ValidationError _validationError;
        public bool IsValidationError => _variantId == ValidationErrorId;

        public global::UnionTypesDemo.ValidationError AsValidationError
        {
            get
            {
                if (_variantId == ValidationErrorId)
                    return _validationError;
                throw new System.InvalidOperationException($"Unable convert to ValidationError. Inner value is {ValueAlias} not ValidationError.");
            }
        }

        public ResultSave(global::UnionTypesDemo.ValidationError validationError)
        {
            System.ArgumentNullException.ThrowIfNull(validationError);
            _variantId = ValidationErrorId;
            _validationError = validationError;
        }

        public static implicit operator ResultSave(global::UnionTypesDemo.ValidationError validationError) => new ResultSave(validationError);
        public static explicit operator global::UnionTypesDemo.ValidationError(ResultSave value)
        {
            if (value._variantId == ValidationErrorId)
                return value._validationError;
            throw new System.InvalidOperationException($"Unable convert to ValidationError. Inner value is {value.ValueAlias} not ValidationError.");
        }

        public bool TryGetValidationError([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out global::UnionTypesDemo.ValidationError value)
        {
            if (_variantId == ValidationErrorId)
            {
                value = _validationError;
                return true;
            }
            else
            {
                value = default;
                return false;
            }
        }

        public TOut Match<TOut>(global::System.Func<global::UnionTypesDemo.Success, TOut> matchSuccess, global::System.Func<global::UnionTypesDemo.ValidationError, TOut> matchValidationError)
        {
            if (_variantId == SuccessId)
                return matchSuccess(_success);
            if (_variantId == ValidationErrorId)
                return matchValidationError(_validationError);
            throw new System.InvalidOperationException("Inner type is unknown");
        }

        public async global::System.Threading.Tasks.Task<TOut> MatchAsync<TOut>(global::System.Func<global::UnionTypesDemo.Success, global::System.Threading.CancellationToken, global::System.Threading.Tasks.Task<TOut>> matchSuccess, global::System.Func<global::UnionTypesDemo.ValidationError, global::System.Threading.CancellationToken, global::System.Threading.Tasks.Task<TOut>> matchValidationError, global::System.Threading.CancellationToken ct)
        {
            if (_variantId == SuccessId)
                return await matchSuccess(_success, ct).ConfigureAwait(false);
            if (_variantId == ValidationErrorId)
                return await matchValidationError(_validationError, ct).ConfigureAwait(false);
            throw new System.InvalidOperationException("Inner type is unknown");
        }

        public void Switch(global::System.Action<global::UnionTypesDemo.Success> switchSuccess, global::System.Action<global::UnionTypesDemo.ValidationError> switchValidationError)
        {
            if (_variantId == SuccessId)
            {
                switchSuccess(_success);
                return;
            }

            if (_variantId == ValidationErrorId)
            {
                switchValidationError(_validationError);
                return;
            }

            throw new System.InvalidOperationException("Inner type is unknown");
        }

        public async global::System.Threading.Tasks.Task SwitchAsync(global::System.Func<global::UnionTypesDemo.Success, global::System.Threading.CancellationToken, global::System.Threading.Tasks.Task> switchSuccess, global::System.Func<global::UnionTypesDemo.ValidationError, global::System.Threading.CancellationToken, global::System.Threading.Tasks.Task> switchValidationError, global::System.Threading.CancellationToken ct)
        {
            if (_variantId == SuccessId)
            {
                await switchSuccess(_success, ct).ConfigureAwait(false);
                return;
            }

            if (_variantId == ValidationErrorId)
            {
                await switchValidationError(_validationError, ct).ConfigureAwait(false);
                return;
            }

            throw new System.InvalidOperationException("Inner type is unknown");
        }

        public global::System.Type ValueType
        {
            get
            {
                if (_variantId == SuccessId)
                    return typeof(global::UnionTypesDemo.Success);
                if (_variantId == ValidationErrorId)
                    return typeof(global::UnionTypesDemo.ValidationError);
                throw new System.InvalidOperationException("Inner type is unknown");
            }
        }

        private string ValueAlias
        {
            get
            {
                if (_variantId == SuccessId)
                    return "Success";
                if (_variantId == ValidationErrorId)
                    return "ValidationError";
                throw new System.InvalidOperationException("Inner type is unknown");
            }
        }

        public override int GetHashCode()
        {
            if (_variantId == SuccessId)
                return _success.GetHashCode();
            if (_variantId == ValidationErrorId)
                return _validationError.GetHashCode();
            throw new System.InvalidOperationException("Inner type is unknown");
        }

        public static bool operator ==(ResultSave? left, ResultSave? right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(ResultSave? left, ResultSave? right)
        {
            return !Equals(left, right);
        }

        public bool Equals(ResultSave? other)
        {
            if (ReferenceEquals(null, other))
            {
                return false;
            }

            if (ReferenceEquals(this, other))
            {
                return true;
            }

            if (ValueType != other.ValueType)
            {
                return false;
            }

            if (_variantId == SuccessId)
                return System.Collections.Generic.EqualityComparer<global::UnionTypesDemo.Success>.Default.Equals(_success, other._success);
            if (_variantId == ValidationErrorId)
                return System.Collections.Generic.EqualityComparer<global::UnionTypesDemo.ValidationError>.Default.Equals(_validationError, other._validationError);
            throw new System.InvalidOperationException("Inner type is unknown");
        }

        public override string ToString()
        {
            if (_variantId == SuccessId)
                return _success.ToString();
            if (_variantId == ValidationErrorId)
                return _validationError.ToString();
            throw new System.InvalidOperationException("Inner type is unknown");
        }

        public override bool Equals(object? other)
        {
            if (ReferenceEquals(null, other))
            {
                return false;
            }

            if (ReferenceEquals(this, other))
            {
                return true;
            }

            if (other.GetType() != typeof(ResultSave))
            {
                return false;
            }

            return Equals((ResultSave)other);
        }
    }
}
#nullable enable
using System;
using System.Runtime.CompilerServices;

namespace N.SourceGenerators.UnionTypes
{
    [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
    sealed class UnionConverterAttribute : Attribute
    {
        public Type FromType { get; }
        public Type ToType { get; }
        public string? MethodName { get; }

        public UnionConverterAttribute(Type fromType, Type toType, string? methodName = null)
        {
            FromType = fromType;
            ToType = toType;
            MethodName = methodName;
        }
    }
}
// <auto-generated>
//   This code was generated by https://github.com/Ne4to/N.SourceGenerators.UnionTypes
//   Feel free to open an issue
// </auto-generated>
#nullable enable
using System;
using System.Runtime.CompilerServices;

namespace N.SourceGenerators.UnionTypes
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = true)]
    sealed class UnionConverterFromAttribute : Attribute
    {
        public Type FromType { get; }

        public UnionConverterFromAttribute(Type fromType)
        {
            FromType = fromType;
        }
    }
}
// <auto-generated>
//   This code was generated by https://github.com/Ne4to/N.SourceGenerators.UnionTypes
//   Feel free to open an issue
// </auto-generated>
#nullable enable
using System;
using System.Runtime.CompilerServices;

namespace N.SourceGenerators.UnionTypes
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = true)]
    sealed class UnionConverterToAttribute : Attribute
    {
        public Type ToType { get; }

        public UnionConverterToAttribute(Type toType)
        {
            ToType = toType;
        }
    }
}
// <auto-generated>
//   This code was generated by https://github.com/Ne4to/N.SourceGenerators.UnionTypes
//   Feel free to open an issue
// </auto-generated>
#nullable enable
using System;
using System.Runtime.CompilerServices;

namespace N.SourceGenerators.UnionTypes
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = true)]
    internal sealed class UnionTypeAttribute : Attribute
    {
        public Type Type { get; }
        public string? Alias { get; }
        public int Order { get; }
        public bool AllowNull { get; set; }
        public object? TypeDiscriminator { get; set; }

        public UnionTypeAttribute(Type type, string? alias = null, [CallerLineNumber] int order = 0)
        {
            Type = type;
            Alias = alias;
            Order = order;
        }
    }
}

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/N.SourceGenerators.UnionTypes

RSCG – AutoConstructor

RSCG – AutoConstructor
 
 

name AutoConstructor
nuget https://www.nuget.org/packages/AutoConstructor/
link https://github.com/k94ll13nn3/AutoConstructor
author Kévin Gallienne

Generating constructor for class with many properties

 

This is how you can use AutoConstructor .

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="AutoConstructor" Version="4.1.1">
	    <PrivateAssets>all</PrivateAssets>
	    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
	  </PackageReference>
	</ItemGroup>
</Project>


The code that you will use is


using QuickConstructorDemo;

var p = new Person("Andrei", "Ignat");

Console.WriteLine(p.FullName());


namespace QuickConstructorDemo;

[AutoConstructor]
internal partial class Person
{
    private readonly string FirstName;
    private readonly string? LastName;
    
    public string FullName() => $"{FirstName} {LastName}";
    
}


 

The code that is generated is

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

[System.AttributeUsage(System.AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
internal sealed class AutoConstructorAttribute : System.Attribute
{
}

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

[System.AttributeUsage(System.AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
internal sealed class AutoConstructorIgnoreAttribute : System.Attribute
{
}

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

[System.AttributeUsage(System.AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
internal sealed class AutoConstructorInjectAttribute : System.Attribute
{
    public AutoConstructorInjectAttribute(string initializer = null, string parameterName = null, System.Type injectedType = null)
    {
        Initializer = initializer;
        ParameterName = parameterName;
        InjectedType = injectedType;
    }

    public string Initializer { get; }

    public string ParameterName { get; }

    public System.Type InjectedType { get; }
}

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by the AutoConstructor source generator.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
#nullable enable
namespace QuickConstructorDemo
{
    partial class Person
    {
        public Person(string FirstName, string? LastName)
        {
            this.FirstName = FirstName;
            this.LastName = LastName;
        }
    }
}

Code and pdf at

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

RSCG – DudNet

RSCG – DudNet
 
 

name DudNet
nuget https://www.nuget.org/packages/Jwshyns.DudNet/
link https://github.com/jwshyns/DudNet
author jwshyns

Generate proxy classes for the principal classes

 

This is how you can use DudNet .

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="Jwshyns.DudNet" Version="1.2.0" />
  </ItemGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
</Project>


The code that you will use is


using DudNetDemo;

var p = new Person();
var p1= new PersonProxy(p);
p1.FirstName = "John";
p1.LastName = "Doe";
Console.WriteLine(p.FullName());
Console.WriteLine(p1.FullName());



using DudNet.Attributes;
using System.Runtime.CompilerServices;

namespace DudNetDemo;
[ProxyService]
public partial class Person : IPerson
{
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
    public string FullName()
    {
        return FirstName + " " + LastName;
    }
}


 

The code that is generated is

using System.Runtime.CompilerServices;
using DudNet.Attributes;
using System.Runtime.CompilerServices;

namespace DudNetDemo;

/// <inheritdoc cref="IPerson"/>
public partial class PersonDud : IPerson {

	public string? FirstName {
		get {
			return (string?) default;
		}
		set {
		}
	}
	public string? LastName {
		get {
			return (string?) default;
		}
		set {
		}
	}
	public string FullName() {
		return (string) default;
	}

}
using System.Runtime.CompilerServices;
using DudNet.Attributes;
using System.Runtime.CompilerServices;

namespace DudNetDemo;

/// <inheritdoc cref="IPerson"/>
public partial class PersonProxy : IPerson {

	private readonly IPerson _service;

	public string? FirstName {
		get {
			Interceptor();
			get_FirstNameInterceptor();
			return _service.FirstName;
		}
		set {
			Interceptor();
			set_FirstNameInterceptor(value);
			_service.FirstName = value;
		}
	}
	public string? LastName {
		get {
			Interceptor();
			get_LastNameInterceptor();
			return _service.LastName;
		}
		set {
			Interceptor();
			set_LastNameInterceptor(value);
			_service.LastName = value;
		}
	}
	public string FullName() {
		Interceptor();
		FullNameInterceptor();
		return _service.FullName();
	}
	partial void Interceptor([CallerMemberName]string callerName = null);
	partial void get_FirstNameInterceptor();
	partial void set_FirstNameInterceptor(string? value);
	partial void get_LastNameInterceptor();
	partial void set_LastNameInterceptor(string? value);
	partial void FullNameInterceptor();

}

Code and pdf at

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

RSCG – MinimalApiBuilder

RSCG – MinimalApiBuilder
 
 

name MinimalApiBuilder
nuget https://www.nuget.org/packages/MinimalApiBuilder/
link https://github.com/JensDll/MinimalApiBuilder
author

Generate Minimal API from classes

 

This is how you can use MinimalApiBuilder .

The code that you start with is


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

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

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.12" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
	  <PackageReference Include="MinimalApiBuilder" Version="1.3.3" />
  </ItemGroup>

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

</Project>


The code that you will use is


using MinimalApiBuilder;

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();
//MinimalApiBuilder.DependencyInjection.AddMinimalApiBuilderEndpoints(builder.Services);
builder.Services.AddMinimalApiBuilderEndpoints();
var app = builder.Build();

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

app.UseAuthorization();

app.MapControllers();

app.MapGet<BasicEndpoint>("/hello");
app.Run();



using Microsoft.AspNetCore.Mvc;
using MinimalApiBuilder;

public partial class BasicEndpoint : MinimalApiBuilderEndpoint
{
    private static string Handle([FromServices] BasicEndpoint endpoint)
    {
        return "Hello, World!";
    }
}


 

The code that is generated is

// <auto-generated>
// This is a MinimalApiBuilder source generated file.
// </auto-generated>

#nullable enable

namespace MinimalApiBuilder
{
    public static class DependencyInjection
    {
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("MinimalApiBuilder.Generator", "1.3.3.0")]
        public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection AddMinimalApiBuilderEndpoints(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services)
        {
            global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped<global::BasicEndpoint>(services);
            return services;
        }
    }
}

// <auto-generated>
// This is a MinimalApiBuilder source generated file.
// </auto-generated>

#nullable enable

public partial class BasicEndpoint : global::MinimalApiBuilder.IEndpoint
{
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("MinimalApiBuilder.Generator", "1.3.3.0")]
    public static global::System.Delegate _auto_generated_Handler { get; } = Handle;
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("MinimalApiBuilder.Generator", "1.3.3.0")]
    public static void _auto_generated_Configure(global::Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder)
    {
    }
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("MinimalApiBuilder.Generator", "1.3.3.0")]
    public static void Configure(global::Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder)
    {
    }
}

Code and pdf at

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

What I have learned from 80+ RSCG

I have analyzed more than 80 Roslyn Source Code Generators –  see https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG .  The conclusions are here:

  1. RSCG is here to stay . There are examples from Microsoft  – and a bunch of other RSCG
  2. First version of RSCG was simple, but VS not performant. The second version is more difficult to implement – but VS is more happy
  3. There are many RSCG for the same thing – for example, generating constructors from fields / properties: https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#constructor . You have to test them like you test any dll
  4. Creating RSCG is difficult – you can add some errors to the code generated and/or warnings and/or more problems. I will put here my findings: https://ignatandrei.github.io/RSCG_Examples/v2/docs/GoodPractices

Adding more data to a result of a task

Every now and then I need to generate , from an array of data, an array of Tasks and then

await Task.WhenAll(TheTaskArray)

The problem is that I need to consolidate the return data of each array with the original array – to make some modifications.

For  example, in the generator of https://ignatandrei.github.io/RSCG_Examples/v2/docs/category/rscg-examples I do something like this

var t = _AllDescriptions
            .Select(it =>GrabReadMe(it))
            .ToArray();
var data = await Task.WhenAll(t);
//now, for each item in data array I want to put something into original _AllDescriptions

My first try was a simple class

public struct TaskWithData<TData, TResult>//: INotifyCompletion
{
    private readonly TData data;
    private readonly Task<TResult> taskToExecute;
 
    public TaskWithData(TData data,Task<TResult> taskToExecute)
    {
        ArgumentNullException.ThrowIfNull(taskToExecute);
        this.data = data;
        this.taskToExecute = taskToExecute;
    }
# region add this to have Task.WhenAll
    public async Task<( TData data, TResult res)> GetTask() {
        var res = await taskToExecute;
        return (data,res);
    }
    public static explicit operator Task<(TData data, TResult res)>(TaskWithData<TData,TResult> b) 
        => b.GetTask() ;

    #endregion
}

And now the code could be written as

var t = _AllDescriptions.Select(
            it => new TaskWithData<Description, string?>(it, GrabReadMe(it))
            )
            .Select(td=>td.GetTask())            
            .ToArray();

        var desc = await Task.WhenAll(t);
        foreach (var item in desc)
        {
            item.data.Readme = item.res;
        }

But I do not like so much … so 2 iterations with extensions

public static class Extensions
{ 
    #region transform to task
    public static Task<( TData data, TResult res)> AddData<TData, TResult>(this Task<TResult> taskToExecute, TData data)
    {
        var td=new TaskWithData<TData, TResult>(data,taskToExecute);
        return td.GetTask();
    }
    public static Task<(TData data, TResult res)>[] SelectTaskWithData<TData, TResult>(this TData[] arr,Func<TData, Task<TResult>> func) {
        return arr.Select(it => func(it).AddData(it)).ToArray();
    }
    #endregion
}

So now the code becomes

var t = _AllDescriptions
            .Select(it =>GrabReadMe(it).AddData(it))
            .ToArray();

or

var t = _AllDescriptions.SelectTaskWithData(GrabReadMe).ToArray();

It was interesting to create this in order to add more data to the return value of a Task

RSCG – DynamicsMapper

RSCG – DynamicsMapper
 
 

name DynamicsMapper
nuget https://www.nuget.org/packages/YC.DynamicsMapper/
link https://github.com/YonatanCohavi/DynamicsMapper/
author Yonatan Cohavi

Mapper for Dataverse client – generates also column names from properties

 

This is how you can use DynamicsMapper .

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="Microsoft.PowerPlatform.Dataverse.Client" Version="1.1.14" />
	  <PackageReference Include="YC.DynamicsMapper" Version="1.0.8" />
	</ItemGroup>
</Project>


The code that you will use is


using NextGenMapperDemo;
var pm = new PersonMapper();
Console.WriteLine(pm.Entityname);



using DynamicsMapper.Abstractions;

namespace NextGenMapperDemo;


[CrmEntity("person")]
public class Person
{
    [CrmField("personid", Mapping = MappingType.PrimaryId)]
    public Guid ID { get; set; }
    [CrmField("name")]

    public string? Name { get; set; }
}

 

The code that is generated is

// <auto-generated />
#nullable enable
using Microsoft.Xrm.Sdk;
using System.Linq;

namespace DynamicsMapper.Extension
{
    public static class EntityExtension
    {
        public static Entity? GetAliasedEntity(this Entity entity, string alias)
        {
            var attributes = entity.Attributes.Where(e => e.Key.StartsWith(alias)).ToArray();
            if (!attributes.Any())
                return null;
            var aliasEntity = new Entity();
            foreach (var attribute in attributes)
            {
                if (!(attribute.Value is AliasedValue aliasedValued))
                    continue;
                if (string.IsNullOrEmpty(aliasEntity.LogicalName))
                    aliasEntity.LogicalName = aliasedValued.EntityLogicalName;
                aliasEntity[aliasedValued.AttributeLogicalName] = aliasedValued.Value;
            }

            return aliasEntity;
        }
    }
}
// <auto-generated />
#nullable enable
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;

namespace DynamicsMapper.Mappers
{
    public interface IEntityMapper<T>
    {
        public string Entityname { get; }
        public ColumnSet Columns { get; }

        public T Map(Entity entity);
        public T? Map(Entity entity, string alias);
        public Entity Map(T model);
    }
}
// <auto-generated />
#nullable enable
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using DynamicsMapper.Extension;
using DynamicsMapper.Mappers;
using System;

namespace NextGenMapperDemo
{
    public class PersonMapper : IEntityMapper<Person>
    {
        private static readonly string[] columns = new[]
        {
            "personid",
            "name"
        };
        public ColumnSet Columns => new ColumnSet(columns);

        private const string entityname = "person";
        public string Entityname => entityname;

        public Entity Map(Person person)
        {
            var entity = new Entity(entityname);
            entity.Id = person.ID;
            entity["name"] = person.Name;
            return entity;
        }

        public Person? Map(Entity entity, string alias) => InternalMap(entity, alias);
        public Person Map(Entity entity) => InternalMap(entity)!;
        private static Person? InternalMap(Entity source, string? alias = null)
        {
            Entity? entity;
            if (string.IsNullOrEmpty(alias))
            {
                entity = source;
            }
            else
            {
                entity = source.GetAliasedEntity(alias);
                if (entity is null)
                    return null;
            }

            if (entity?.LogicalName != entityname)
                throw new ArgumentException($"entity LogicalName expected to be {entityname} recived: {entity?.LogicalName}", "entity");
            var person = new Person();
            person.ID = entity.GetAttributeValue<Guid>("personid");
            person.Name = entity.GetAttributeValue<string?>("name");
            return person;
        }
    }
}

Code and pdf at

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

RSCG – UnitGenerator

RSCG – UnitGenerator
 
 

name UnitGenerator
nuget https://www.nuget.org/packages/UnitGenerator/
link https://github.com/Cysharp/UnitGenerator
author Cysharp, Inc

Generating classes instead of value objects( e.g. int)

 

This is how you can use UnitGenerator .

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="UnitGenerator" Version="1.5.1">
      <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 StronglyDemo;

Person p = new();
//p.SetBirthDate(1970, 4, 16);
p.SetBirthDate(new YearId(1970) , new MonthId(4),new DayId( 16));
Console.WriteLine(p.BirthDate);



using UnitGenerator;

namespace StronglyDemo;


[UnitOf(typeof(int))]
public partial struct YearId { }

[UnitOf(typeof(int))]
public partial struct MonthId { }

[UnitOf(typeof(int))]
public partial struct DayId { }

internal class Person
{
    public DateTime BirthDate { get; internal set; }
    public void SetBirthDate(YearId yearId,MonthId monthId,DayId dayId)
    {
        BirthDate = new DateTime(yearId.AsPrimitive(), monthId.AsPrimitive(), dayId.AsPrimitive());
    }
}


 

The code that is generated is

// <auto-generated>
// THIS (.cs) FILE IS GENERATED BY UnitGenerator. DO NOT CHANGE IT.
// </auto-generated>
#pragma warning disable CS8669
using System;
using System.Globalization;
#if NET7_0_OR_GREATER
using System.Numerics;
#endif
namespace StronglyDemo
{
    [System.ComponentModel.TypeConverter(typeof(DayIdTypeConverter))]
    readonly partial struct DayId 
        : IEquatable<DayId>
#if NET7_0_OR_GREATER
        , IEqualityOperators<DayId, DayId, bool>
#endif    
    {
        readonly int value;

        public int AsPrimitive() => value;

        public DayId(int value)
        {
            this.value = value;
        }
        
        public static explicit operator int(DayId value)
        {
            return value.value;
        }

        public static explicit operator DayId(int value)
        {
            return new DayId(value);
        }

        public bool Equals(DayId other)
        {
            return value.Equals(other.value);
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            var t = obj.GetType();
            if (t == typeof(DayId))
            {
                return Equals((DayId)obj);
            }
            if (t == typeof(int))
            {
                return value.Equals((int)obj);
            }

            return value.Equals(obj);
        }
        
        public static bool operator ==(DayId x, DayId y)
        {
            return x.value.Equals(y.value);
        }

        public static bool operator !=(DayId x, DayId y)
        {
            return !x.value.Equals(y.value);
        }

        public override int GetHashCode()
        {
            return value.GetHashCode();
        }

        public override string ToString() => value.ToString();

        // Default
        
        private class DayIdTypeConverter : System.ComponentModel.TypeConverter
        {
            private static readonly Type WrapperType = typeof(DayId);
            private static readonly Type ValueType = typeof(int);

            public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
            {
                if (sourceType == WrapperType || sourceType == ValueType)
                {
                    return true;
                }

                return base.CanConvertFrom(context, sourceType);
            }

            public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType)
            {
                if (destinationType == WrapperType || destinationType == ValueType)
                {
                    return true;
                }

                return base.CanConvertTo(context, destinationType);
            }

            public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
            {
                if (value != null)
                {
                    var t = value.GetType();
                    if (t == typeof(DayId))
                    {
                        return (DayId)value;
                    }
                    if (t == typeof(int))
                    {
                        return new DayId((int)value);
                    }
                }

                return base.ConvertFrom(context, culture, value);
            }

            public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
            {
                if (value is DayId wrappedValue)
                {
                    if (destinationType == WrapperType)
                    {
                        return wrappedValue;
                    }

                    if (destinationType == ValueType)
                    {
                        return wrappedValue.AsPrimitive();
                    }
                }

                return base.ConvertTo(context, culture, value, destinationType);
            }
        }
    }
}

// <auto-generated>
// THIS (.cs) FILE IS GENERATED BY UnitGenerator. DO NOT CHANGE IT.
// </auto-generated>
#pragma warning disable CS8669
using System;
using System.Globalization;
#if NET7_0_OR_GREATER
using System.Numerics;
#endif
namespace StronglyDemo
{
    [System.ComponentModel.TypeConverter(typeof(MonthIdTypeConverter))]
    readonly partial struct MonthId 
        : IEquatable<MonthId>
#if NET7_0_OR_GREATER
        , IEqualityOperators<MonthId, MonthId, bool>
#endif    
    {
        readonly int value;

        public int AsPrimitive() => value;

        public MonthId(int value)
        {
            this.value = value;
        }
        
        public static explicit operator int(MonthId value)
        {
            return value.value;
        }

        public static explicit operator MonthId(int value)
        {
            return new MonthId(value);
        }

        public bool Equals(MonthId other)
        {
            return value.Equals(other.value);
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            var t = obj.GetType();
            if (t == typeof(MonthId))
            {
                return Equals((MonthId)obj);
            }
            if (t == typeof(int))
            {
                return value.Equals((int)obj);
            }

            return value.Equals(obj);
        }
        
        public static bool operator ==(MonthId x, MonthId y)
        {
            return x.value.Equals(y.value);
        }

        public static bool operator !=(MonthId x, MonthId y)
        {
            return !x.value.Equals(y.value);
        }

        public override int GetHashCode()
        {
            return value.GetHashCode();
        }

        public override string ToString() => value.ToString();

        // Default
        
        private class MonthIdTypeConverter : System.ComponentModel.TypeConverter
        {
            private static readonly Type WrapperType = typeof(MonthId);
            private static readonly Type ValueType = typeof(int);

            public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
            {
                if (sourceType == WrapperType || sourceType == ValueType)
                {
                    return true;
                }

                return base.CanConvertFrom(context, sourceType);
            }

            public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType)
            {
                if (destinationType == WrapperType || destinationType == ValueType)
                {
                    return true;
                }

                return base.CanConvertTo(context, destinationType);
            }

            public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
            {
                if (value != null)
                {
                    var t = value.GetType();
                    if (t == typeof(MonthId))
                    {
                        return (MonthId)value;
                    }
                    if (t == typeof(int))
                    {
                        return new MonthId((int)value);
                    }
                }

                return base.ConvertFrom(context, culture, value);
            }

            public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
            {
                if (value is MonthId wrappedValue)
                {
                    if (destinationType == WrapperType)
                    {
                        return wrappedValue;
                    }

                    if (destinationType == ValueType)
                    {
                        return wrappedValue.AsPrimitive();
                    }
                }

                return base.ConvertTo(context, culture, value, destinationType);
            }
        }
    }
}

// <auto-generated>
// THIS (.cs) FILE IS GENERATED BY UnitGenerator. DO NOT CHANGE IT.
// </auto-generated>
#pragma warning disable CS8669
using System;
using System.Globalization;
#if NET7_0_OR_GREATER
using System.Numerics;
#endif
namespace StronglyDemo
{
    [System.ComponentModel.TypeConverter(typeof(YearIdTypeConverter))]
    readonly partial struct YearId 
        : IEquatable<YearId>
#if NET7_0_OR_GREATER
        , IEqualityOperators<YearId, YearId, bool>
#endif    
    {
        readonly int value;

        public int AsPrimitive() => value;

        public YearId(int value)
        {
            this.value = value;
        }
        
        public static explicit operator int(YearId value)
        {
            return value.value;
        }

        public static explicit operator YearId(int value)
        {
            return new YearId(value);
        }

        public bool Equals(YearId other)
        {
            return value.Equals(other.value);
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            var t = obj.GetType();
            if (t == typeof(YearId))
            {
                return Equals((YearId)obj);
            }
            if (t == typeof(int))
            {
                return value.Equals((int)obj);
            }

            return value.Equals(obj);
        }
        
        public static bool operator ==(YearId x, YearId y)
        {
            return x.value.Equals(y.value);
        }

        public static bool operator !=(YearId x, YearId y)
        {
            return !x.value.Equals(y.value);
        }

        public override int GetHashCode()
        {
            return value.GetHashCode();
        }

        public override string ToString() => value.ToString();

        // Default
        
        private class YearIdTypeConverter : System.ComponentModel.TypeConverter
        {
            private static readonly Type WrapperType = typeof(YearId);
            private static readonly Type ValueType = typeof(int);

            public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
            {
                if (sourceType == WrapperType || sourceType == ValueType)
                {
                    return true;
                }

                return base.CanConvertFrom(context, sourceType);
            }

            public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType)
            {
                if (destinationType == WrapperType || destinationType == ValueType)
                {
                    return true;
                }

                return base.CanConvertTo(context, destinationType);
            }

            public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
            {
                if (value != null)
                {
                    var t = value.GetType();
                    if (t == typeof(YearId))
                    {
                        return (YearId)value;
                    }
                    if (t == typeof(int))
                    {
                        return new YearId((int)value);
                    }
                }

                return base.ConvertFrom(context, culture, value);
            }

            public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
            {
                if (value is YearId wrappedValue)
                {
                    if (destinationType == WrapperType)
                    {
                        return wrappedValue;
                    }

                    if (destinationType == ValueType)
                    {
                        return wrappedValue.AsPrimitive();
                    }
                }

                return base.ConvertTo(context, culture, value, destinationType);
            }
        }
    }
}

// <auto-generated>
// THIS (.cs) FILE IS GENERATED BY UnitGenerator. DO NOT CHANGE IT.
// </auto-generated>
#pragma warning disable CS8669
#pragma warning disable CS8625
using System;
#if NET7_0_OR_GREATER
using System.Numerics;
#endif

namespace UnitGenerator
{
    [AttributeUsage(AttributeTargets.Struct, AllowMultiple = false)]
    internal class UnitOfAttribute : Attribute
    {
        public Type Type { get; }
        public UnitGenerateOptions Options { get; }
        public UnitArithmeticOperators ArithmeticOperators { get; set; } = UnitArithmeticOperators.All;
        public string ToStringFormat { get; set; }

        public UnitOfAttribute(Type type, UnitGenerateOptions options = UnitGenerateOptions.None)
        {
            this.Type = type;
            this.Options = options;
        }
    }
    
    [Flags]
    internal enum UnitGenerateOptions
    {
        None = 0,
        ImplicitOperator = 1,
        ParseMethod = 1 << 1,
        MinMaxMethod = 1 << 2,
        ArithmeticOperator = 1 << 3,
        ValueArithmeticOperator = 1 << 4,
        Comparable = 1 << 5,
        Validate = 1 << 6,
        JsonConverter = 1 << 7,
        MessagePackFormatter = 1 << 8,
        DapperTypeHandler = 1 << 9,
        EntityFrameworkValueConverter = 1 << 10,
        WithoutComparisonOperator = 1 << 11,
        JsonConverterDictionaryKeySupport = 1 << 12,
        Normalize = 1 << 13,
    }

    [Flags]
    internal enum UnitArithmeticOperators
    {
        All = Addition | Subtraction | Multiply | Division | Increment | Decrement,
        Addition = 1,
        Subtraction = 1 << 1,
        Multiply = 1 << 2,
        Division = 1 << 3,
        Increment = 1 << 4,
        Decrement = 1 << 5,
    }
}

Code and pdf at

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

RSCG – StaticReflection

RSCG – StaticReflection
 
 

name StaticReflection
nuget https://www.nuget.org/packages/FastStaticReflection/
https://www.nuget.org/packages/FastStaticReflection.CodeGen/
link https://github.com/Cricle/StaticReflection/
author Cricle

Call prop/methods on classes

 

This is how you can use StaticReflection .

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="FastStaticReflection" Version="1.0.0-preview.3" />
    <PackageReference Include="FastStaticReflection.CodeGen" Version="1.0.0-preview.3" />
  </ItemGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
</Project>


The code that you will use is


using StaticReflection;
using StaticReflectionDemo;

var p = new Person();

PersonReflection.Instance.SetProperty(p, "FirstName","Andrei");
PersonReflection.Instance.SetProperty(p, "LastName", "Ignat");

Console.WriteLine(p.Name());


using StaticReflection.Annotions;

namespace StaticReflectionDemo;
[StaticReflection]
internal partial class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Name()
    {
        return $"{FirstName} {LastName}";
    }
}


 

The code that is generated is

// <auto-generated/>
#pragma warning disable CS9082
#pragma warning disable CS8669
namespace StaticReflectionDemo
{
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("StaticReflection.CodeGen", "1.0.0")]
    [global::System.Diagnostics.DebuggerStepThrough]
    [global::System.Runtime.CompilerServices.CompilerGenerated]
    internal sealed class PersonReflection : StaticReflection.ITypeDefine
    {
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("StaticReflection.CodeGen", "1.0.0")]
        [global::System.Diagnostics.DebuggerStepThrough]
        [global::System.Runtime.CompilerServices.CompilerGenerated]
        internal sealed class Person0PReflection : StaticReflection.IMemberInvokeDefine<StaticReflectionDemo.Person, string>, StaticReflection.IPropertyDefine, StaticReflection.IMemberAnonymousInvokeDefine
        {
            public static readonly Person0PReflection Instance = new Person0PReflection();
            public System.Type DeclareType { get; } = typeof(StaticReflectionDemo.Person);
            public System.String Name { get; } = "FirstName";
            public System.String MetadataName { get; } = "FirstName";
            public System.Boolean IsVirtual { get; } = false;
            public System.Boolean IsStatic { get; } = false;
            public System.Boolean IsOverride { get; } = false;
            public System.Boolean IsAbstract { get; } = false;
            public System.Boolean IsSealed { get; } = false;
            public System.Boolean IsDefinition { get; } = true;
            public System.Boolean IsExtern { get; } = false;
            public System.Boolean IsImplicitlyDeclared { get; } = false;
            public System.Boolean CanBeReferencedByName { get; } = true;
            public System.Boolean IsPublic { get; } = true;
            public System.Boolean IsPrivate { get; } = false;
            public System.Boolean IsProtected { get; } = false;
            public System.Boolean IsInternal { get; } = false;
            public System.Type PropertyType { get; } = typeof(string);
            public System.Boolean CanRead { get; } = true;
            public System.Boolean CanWrite { get; } = true;
            public System.Boolean IsRequired { get; } = false;
            public System.Boolean IsWithEvents { get; } = false;
            public System.Boolean ReturnsByRef { get; } = false;
            public System.Boolean ReturnsByRefReadonly { get; } = false;
            public System.Collections.Generic.IReadOnlyList<System.Attribute> GetterAttributes { get; } = new System.Attribute[]
            {
            };
            public System.Collections.Generic.IReadOnlyList<System.Attribute> SetterAttributes { get; } = new System.Attribute[]
            {
            };
            public System.Collections.Generic.IReadOnlyList<System.Attribute> Attributes { get; } = new System.Attribute[]
            {
            };

            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
            public string GetValue(Person instance)
            {
                return instance.FirstName;
            }

            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
            public void SetValue(Person instance, string value)
            {
                instance.FirstName = value;
            }

            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
            public void SetValueAnonymous(object instance, object value)
            {
                SetValue((StaticReflectionDemo.Person)instance, (string)value);
            }

            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
            public object GetValueAnonymous(object instance)
            {
                return (object)GetValue((StaticReflectionDemo.Person)instance);
            }
        }

        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("StaticReflection.CodeGen", "1.0.0")]
        [global::System.Diagnostics.DebuggerStepThrough]
        [global::System.Runtime.CompilerServices.CompilerGenerated]
        internal sealed class Person1PReflection : StaticReflection.IMemberInvokeDefine<StaticReflectionDemo.Person, string>, StaticReflection.IPropertyDefine, StaticReflection.IMemberAnonymousInvokeDefine
        {
            public static readonly Person1PReflection Instance = new Person1PReflection();
            public System.Type DeclareType { get; } = typeof(StaticReflectionDemo.Person);
            public System.String Name { get; } = "LastName";
            public System.String MetadataName { get; } = "LastName";
            public System.Boolean IsVirtual { get; } = false;
            public System.Boolean IsStatic { get; } = false;
            public System.Boolean IsOverride { get; } = false;
            public System.Boolean IsAbstract { get; } = false;
            public System.Boolean IsSealed { get; } = false;
            public System.Boolean IsDefinition { get; } = true;
            public System.Boolean IsExtern { get; } = false;
            public System.Boolean IsImplicitlyDeclared { get; } = false;
            public System.Boolean CanBeReferencedByName { get; } = true;
            public System.Boolean IsPublic { get; } = true;
            public System.Boolean IsPrivate { get; } = false;
            public System.Boolean IsProtected { get; } = false;
            public System.Boolean IsInternal { get; } = false;
            public System.Type PropertyType { get; } = typeof(string);
            public System.Boolean CanRead { get; } = true;
            public System.Boolean CanWrite { get; } = true;
            public System.Boolean IsRequired { get; } = false;
            public System.Boolean IsWithEvents { get; } = false;
            public System.Boolean ReturnsByRef { get; } = false;
            public System.Boolean ReturnsByRefReadonly { get; } = false;
            public System.Collections.Generic.IReadOnlyList<System.Attribute> GetterAttributes { get; } = new System.Attribute[]
            {
            };
            public System.Collections.Generic.IReadOnlyList<System.Attribute> SetterAttributes { get; } = new System.Attribute[]
            {
            };
            public System.Collections.Generic.IReadOnlyList<System.Attribute> Attributes { get; } = new System.Attribute[]
            {
            };

            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
            public string GetValue(Person instance)
            {
                return instance.LastName;
            }

            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
            public void SetValue(Person instance, string value)
            {
                instance.LastName = value;
            }

            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
            public void SetValueAnonymous(object instance, object value)
            {
                SetValue((StaticReflectionDemo.Person)instance, (string)value);
            }

            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
            public object GetValueAnonymous(object instance)
            {
                return (object)GetValue((StaticReflectionDemo.Person)instance);
            }
        }

        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("StaticReflection.CodeGen", "1.0.0")]
        [global::System.Diagnostics.DebuggerStepThrough]
        [global::System.Runtime.CompilerServices.CompilerGenerated]
        internal sealed class Person0MReflection : StaticReflection.IMethodDefine, StaticReflection.Invoking.IArgsMethod<StaticReflectionDemo.Person, string>, StaticReflection.Invoking.IArgs0AnonymousMethod, StaticReflection.Invoking.IUsualArgsMethod<StaticReflectionDemo.Person, string>, StaticReflection.Invoking.IUsualArgs0AnonymousMethod
        {
            public static readonly Person0MReflection Instance = new Person0MReflection();
            private Person0MReflection()
            {
            }

            public System.String Name { get; } = "Name";
            public System.String MetadataName { get; } = "Name";
            public System.Boolean IsVirtual { get; } = false;
            public System.Boolean IsStatic { get; } = false;
            public System.Boolean IsOverride { get; } = false;
            public System.Boolean IsAbstract { get; } = false;
            public System.Boolean IsSealed { get; } = false;
            public System.Boolean IsDefinition { get; } = true;
            public System.Boolean IsExtern { get; } = false;
            public System.Boolean IsImplicitlyDeclared { get; } = false;
            public System.Boolean CanBeReferencedByName { get; } = true;
            public System.Boolean IsPublic { get; } = true;
            public System.Boolean IsPrivate { get; } = false;
            public System.Boolean IsProtected { get; } = false;
            public System.Boolean IsInternal { get; } = false;
            public System.Collections.Generic.IReadOnlyList<System.Attribute> Attributes { get; } = new System.Attribute[]
            {
            };
            public System.Type DeclareType { get; } = typeof(StaticReflectionDemo.Person);
            public System.Boolean ReturnsByRef { get; } = false;
            public StaticReflection.StaticMethodKind MethodKind { get; } = StaticReflection.StaticMethodKind.Ordinary;
            public StaticReflection.StaticRefKind RefKind { get; } = StaticReflection.StaticRefKind.None;
            public StaticReflection.StaticNullableAnnotation ReturnNullableAnnotation { get; } = StaticReflection.StaticNullableAnnotation.NotAnnotated;
            public StaticReflection.StaticNullableAnnotation ReceiverNullableAnnotation { get; } = StaticReflection.StaticNullableAnnotation.NotAnnotated;
            public System.Boolean ReturnsByRefReadonly { get; } = false;
            public System.Type ReturnType { get; } = typeof(string);
            public System.Collections.Generic.IReadOnlyList<System.Type> ArgumentTypes { get; } = new System.Type[]
            {
            };
            public System.Boolean IsGenericMethod { get; } = false;
            public System.Int32 Arity { get; } = 0;
            public System.Boolean IsExtensionMethod { get; } = false;
            public System.Boolean IsAsync { get; } = false;
            public System.Boolean IsVararg { get; } = false;
            public System.Boolean IsCheckedBuiltin { get; } = false;
            public System.Boolean HidesBaseMethodsByName { get; } = false;
            public System.Boolean ReturnsVoid { get; } = false;
            public System.Boolean IsReadOnly { get; } = false;
            public System.Boolean IsInitOnly { get; } = false;
            public System.Boolean IsPartialDefinition { get; } = false;
            public System.Boolean IsConditional { get; } = false;
            public System.Collections.Generic.IReadOnlyList<StaticReflection.ITypeArgumentDefine> TypeArguments { get; } = new StaticReflection.ITypeArgumentDefine[]
            {
            };
            public System.Collections.Generic.IReadOnlyList<System.Attribute> ReturnTypeAttributes { get; } = new System.Attribute[]
            {
            };

            [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
            public 
#if !NET7_0_OR_GREATER
            unsafe 
#endif
            ref string Invoke(StaticReflectionDemo.Person instance)
            {
                ref string result = ref System.Runtime.CompilerServices.Unsafe.AsRef(instance.Name());
                return ref result;
            }

            public 
#if !NET7_0_OR_GREATER
            unsafe 
#endif
            ref object InvokeAnonymous(object instance)
            {
                return ref System.Runtime.CompilerServices.Unsafe.AsRef<object>(Invoke((StaticReflectionDemo.Person)instance));
            }

            [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
            public string InvokeUsual(StaticReflectionDemo.Person instance)
            {
                return instance.Name();
            }

            public object InvokeUsualAnonymous(object instance)
            {
                return InvokeUsual((StaticReflectionDemo.Person)instance);
            }
        }

        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("StaticReflection.CodeGen", "1.0.0")]
        [global::System.Diagnostics.DebuggerStepThrough]
        [global::System.Runtime.CompilerServices.CompilerGenerated]
        internal sealed class Person0CReflection : StaticReflection.IConstructorDefine, StaticReflection.Invoking.IArgsMethod<StaticReflectionDemo.Person, StaticReflectionDemo.Person>, StaticReflection.Invoking.IArgs0AnonymousMethod, StaticReflection.Invoking.IUsualArgsMethod<StaticReflectionDemo.Person, StaticReflectionDemo.Person>, StaticReflection.Invoking.IUsualArgs0AnonymousMethod
        {
            public static readonly Person0CReflection Instance = new Person0CReflection();
            private Person0CReflection()
            {
            }

            public System.String Name { get; } = ".ctor";
            public System.String MetadataName { get; } = ".ctor";
            public System.Boolean IsVirtual { get; } = false;
            public System.Boolean IsStatic { get; } = false;
            public System.Boolean IsOverride { get; } = false;
            public System.Boolean IsAbstract { get; } = false;
            public System.Boolean IsSealed { get; } = false;
            public System.Boolean IsDefinition { get; } = true;
            public System.Boolean IsExtern { get; } = false;
            public System.Boolean IsImplicitlyDeclared { get; } = true;
            public System.Boolean CanBeReferencedByName { get; } = false;
            public System.Boolean IsPublic { get; } = true;
            public System.Boolean IsPrivate { get; } = false;
            public System.Boolean IsProtected { get; } = false;
            public System.Boolean IsInternal { get; } = false;
            public System.Collections.Generic.IReadOnlyList<System.Attribute> Attributes { get; } = new System.Attribute[]
            {
            };
            public System.Type DeclareType { get; } = typeof(StaticReflectionDemo.Person);
            public System.Boolean ReturnsByRef { get; } = false;
            public StaticReflection.StaticMethodKind MethodKind { get; } = StaticReflection.StaticMethodKind.Constructor;
            public StaticReflection.StaticRefKind RefKind { get; } = StaticReflection.StaticRefKind.None;
            public StaticReflection.StaticNullableAnnotation ReturnNullableAnnotation { get; } = StaticReflection.StaticNullableAnnotation.NotAnnotated;
            public StaticReflection.StaticNullableAnnotation ReceiverNullableAnnotation { get; } = StaticReflection.StaticNullableAnnotation.NotAnnotated;
            public System.Boolean ReturnsByRefReadonly { get; } = false;
            public System.Type ReturnType { get; } = typeof(StaticReflectionDemo.Person);
            public System.Collections.Generic.IReadOnlyList<System.Type> ArgumentTypes { get; } = new System.Type[]
            {
            };
            public System.Boolean IsGenericMethod { get; } = false;
            public System.Int32 Arity { get; } = 0;
            public System.Boolean IsExtensionMethod { get; } = false;
            public System.Boolean IsAsync { get; } = false;
            public System.Boolean IsVararg { get; } = false;
            public System.Boolean IsCheckedBuiltin { get; } = false;
            public System.Boolean HidesBaseMethodsByName { get; } = false;
            public System.Boolean ReturnsVoid { get; } = true;
            public System.Boolean IsReadOnly { get; } = false;
            public System.Boolean IsInitOnly { get; } = false;
            public System.Boolean IsPartialDefinition { get; } = false;
            public System.Boolean IsConditional { get; } = false;
            public System.Collections.Generic.IReadOnlyList<StaticReflection.ITypeArgumentDefine> TypeArguments { get; } = new StaticReflection.ITypeArgumentDefine[]
            {
            };
            public System.Collections.Generic.IReadOnlyList<System.Attribute> ReturnTypeAttributes { get; } = new System.Attribute[]
            {
            };

            [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
            public 
#if !NET7_0_OR_GREATER
            unsafe 
#endif
            ref StaticReflectionDemo.Person Invoke(StaticReflectionDemo.Person instance)
            {
                ref StaticReflectionDemo.Person result = ref System.Runtime.CompilerServices.Unsafe.AsRef(new Person());
                return ref result;
            }

            public 
#if !NET7_0_OR_GREATER
            unsafe 
#endif
            ref object InvokeAnonymous(object instance)
            {
                return ref System.Runtime.CompilerServices.Unsafe.AsRef<object>(Invoke((StaticReflectionDemo.Person)instance));
            }

            [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
            public StaticReflectionDemo.Person InvokeUsual(StaticReflectionDemo.Person instance)
            {
                return new Person();
            }

            public object InvokeUsualAnonymous(object instance)
            {
                return InvokeUsual((StaticReflectionDemo.Person)instance);
            }
        }

        public static readonly PersonReflection Instance = new PersonReflection();
        public System.Type DeclareType { get; } = typeof(StaticReflectionDemo.Person);
        public System.String Name { get; } = "Person";
        public System.String MetadataName { get; } = "Person";
        public System.Boolean IsVirtual { get; } = false;
        public System.Boolean IsStatic { get; } = false;
        public System.Boolean IsOverride { get; } = false;
        public System.Boolean IsAbstract { get; } = false;
        public System.Boolean IsSealed { get; } = false;
        public System.Boolean IsDefinition { get; } = true;
        public System.Boolean IsExtern { get; } = false;
        public System.Boolean IsImplicitlyDeclared { get; } = false;
        public System.Boolean CanBeReferencedByName { get; } = true;
        public System.Boolean IsPublic { get; } = false;
        public System.Boolean IsPrivate { get; } = false;
        public System.Boolean IsProtected { get; } = false;
        public System.Boolean IsInternal { get; } = true;
        public System.Type? BaseType { get; } = typeof(StaticReflectionDemo.Person);
        public System.Boolean IsReferenceType { get; } = true;
        public System.Boolean IsValueType { get; } = false;
        public System.Boolean IsAnonymousType { get; } = false;
        public System.Boolean IsTupleType { get; } = false;
        public System.Boolean IsNativeIntegerType { get; } = false;
        public System.Boolean IsRefLikeType { get; } = false;
        public System.Boolean IsUnmanagedType { get; } = false;
        public System.Boolean IsReadOnly { get; } = false;
        public System.Boolean IsRecord { get; } = false;
        public System.Int32 TypeKind { get; } = 2;
        public StaticReflection.StaticNullableAnnotation NullableAnnotation { get; } = StaticReflection.StaticNullableAnnotation.None;
        public System.Collections.Generic.IReadOnlyList<System.String> Interfaces { get; } = new System.String[]
        {
        };
        public System.Collections.Generic.IReadOnlyList<System.String> AllInterfaces { get; } = new System.String[]
        {
        };
        public System.Collections.Generic.IReadOnlyList<System.Attribute> Attributes { get; } = new System.Attribute[]
        {
            new StaticReflection.Annotions.StaticReflectionAttribute()
            {
            }
        };
        public System.Collections.Generic.IReadOnlyList<StaticReflection.IPropertyDefine> Properties { get; } = new StaticReflection.IPropertyDefine[]
        {
            Person0PReflection.Instance,
            Person1PReflection.Instance
        };
        public System.Collections.Generic.IReadOnlyList<StaticReflection.IMethodDefine> Methods { get; } = new StaticReflection.IMethodDefine[]
        {
            Person0MReflection.Instance
        };
        public System.Collections.Generic.IReadOnlyList<StaticReflection.IEventDefine> Events { get; } = new StaticReflection.IEventDefine[]
        {
        };
        public System.Collections.Generic.IReadOnlyList<StaticReflection.IFieldDefine> Fields { get; } = new StaticReflection.IFieldDefine[]
        {
        };
        public System.Collections.Generic.IReadOnlyList<StaticReflection.IConstructorDefine> Constructors { get; } = new StaticReflection.IConstructorDefine[]
        {
            Person0CReflection.Instance
        };
    }
}

Code and pdf at

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

RSCG – CredFetoEnum

RSCG – CredFetoEnum
 
 

name CredFetoEnum
nuget https://www.nuget.org/packages/Credfeto.Enumeration.Source.Generation/
link https://github.com/credfeto/credfeto-enum-source-generation
author Mark Ridgwell

Enum / description to string

 

This is how you can use CredFetoEnum .

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="Credfeto.Enumeration.Source.Generation" Version="1.1.0.138" OutputItemType="Analyzer">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
</Project>


The code that you will use is


using EnumClassDemo;
Console.WriteLine(Colors.None.GetName());
Console.WriteLine(Colors.None.GetDescription());


using System.ComponentModel;

namespace EnumClassDemo;

public enum Colors
{
    [Description("This should be never seen")]
    None =0,
    Red,
    Green,
    Blue,
}


 

The code that is generated is

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

namespace EnumClassDemo;

[GeneratedCode(tool: "Credfeto.Enumeration.Source.Generation.EnumGenerator", version: "1.1.0.138+a4e45a10ca3da5e916ae17843913bfff8c33cdef")]
public static class ColorsGeneratedExtensions
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static string GetName(this Colors value)
    {
        return value switch
        {
            Colors.None => nameof(Colors.None),
            Colors.Red => nameof(Colors.Red),
            Colors.Green => nameof(Colors.Green),
            Colors.Blue => nameof(Colors.Blue),
            _ => ThrowInvalidEnumMemberException(value: value)
        };
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static string GetDescription(this Colors value)
    {
        return value switch
        {
            Colors.None => "This should be never seen",
            _ => GetName(value)
        };
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool IsDefined(this Colors value)
    {
        return value is Colors.None or Colors.Red or Colors.Green or Colors.Blue;
    }

    public static string ThrowInvalidEnumMemberException(this Colors value)
    {
        #if NET7_0_OR_GREATER
        throw new UnreachableException(message: "Colors: Unknown enum member");
        #else
        throw new ArgumentOutOfRangeException(nameof(value), actualValue: value, message: "Unknown enum member");
        #endif
    }
}

Code and pdf at

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

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.