Category: RSCG

RSCG – System.Text.RegularExpressions

RSCG – System.Text.RegularExpressions
 
 

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

Regex compiled

 

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

The code that you start with is

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<Project Sdk="Microsoft.NET.Sdk">
 
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
    <PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
    </PropertyGroup>
 
</Project>

The code that you will use is

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
using System.Text.RegularExpressions;
 
namespace Demo;
 
public partial class DemoRegex
{
    [GeneratedRegex("abc|def", RegexOptions.IgnoreCase, "en-US")]
    private static partial Regex AbcOrDefGeneratedRegex();
 
    public static bool EvaluateText(string text)
    {
        return (AbcOrDefGeneratedRegex().IsMatch(text));
         
    }
}

 

The code that is generated is

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// <auto-generated/>
#nullable enable
#pragma warning disable CS0162 // Unreachable code
#pragma warning disable CS0164 // Unreferenced label
#pragma warning disable CS0219 // Variable assigned but never used
 
namespace Demo
{
    partial class DemoRegex
    {
        /// <remarks>
        /// Pattern explanation:<br/>
        /// <code>
        /// ○ Match with 2 alternative expressions, atomically.<br/>
        ///     ○ Match a sequence of expressions.<br/>
        ///         ○ Match a character in the set [Aa].<br/>
        ///         ○ Match a character in the set [Bb].<br/>
        ///         ○ Match a character in the set [Cc].<br/>
        ///     ○ Match a sequence of expressions.<br/>
        ///         ○ Match a character in the set [Dd].<br/>
        ///         ○ Match a character in the set [Ee].<br/>
        ///         ○ Match a character in the set [Ff].<br/>
        /// </code>
        /// </remarks>
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "7.0.8.17405")]
        private static partial global::System.Text.RegularExpressions.Regex AbcOrDefGeneratedRegex() => global::System.Text.RegularExpressions.Generated.AbcOrDefGeneratedRegex_0.Instance;
    }
}
 
namespace System.Text.RegularExpressions.Generated
{
    using System;
    using System.CodeDom.Compiler;
    using System.Collections;
    using System.ComponentModel;
    using System.Globalization;
    using System.Runtime.CompilerServices;
    using System.Text.RegularExpressions;
    using System.Threading;
 
    /// <summary>Custom <see cref="Regex"/>-derived type for the AbcOrDefGeneratedRegex method.</summary>
    [GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "7.0.8.17405")]
    file sealed class AbcOrDefGeneratedRegex_0 : Regex
    {
        /// <summary>Cached, thread-safe singleton instance.</summary>
        internal static readonly AbcOrDefGeneratedRegex_0 Instance = new();
     
        /// <summary>Initializes the instance.</summary>
        private AbcOrDefGeneratedRegex_0()
        {
            base.pattern = "abc|def";
            base.roptions = RegexOptions.IgnoreCase;
            ValidateMatchTimeout(Utilities.s_defaultTimeout);
            base.internalMatchTimeout = Utilities.s_defaultTimeout;
            base.factory = new RunnerFactory();
            base.capsize = 1;
        }
     
        /// <summary>Provides a factory for creating <see cref="RegexRunner"/> instances to be used by methods on <see cref="Regex"/>.</summary>
        private sealed class RunnerFactory : RegexRunnerFactory
        {
            /// <summary>Creates an instance of a <see cref="RegexRunner"/> used by methods on <see cref="Regex"/>.</summary>
            protected override RegexRunner CreateInstance() => new Runner();
         
            /// <summary>Provides the runner that contains the custom logic implementing the specified regular expression.</summary>
            private sealed class Runner : RegexRunner
            {
                /// <summary>Scan the <paramref name="inputSpan"/> starting from base.runtextstart for the next match.</summary>
                /// <param name="inputSpan">The text being scanned by the regular expression.</param>
                protected override void Scan(ReadOnlySpan<char> inputSpan)
                {
                    // Search until we can't find a valid starting position, we find a match, or we reach the end of the input.
                    while (TryFindNextPossibleStartingPosition(inputSpan) &&
                           !TryMatchAtCurrentPosition(inputSpan) &&
                           base.runtextpos != inputSpan.Length)
                    {
                        base.runtextpos++;
                        if (Utilities.s_hasTimeout)
                        {
                            base.CheckTimeout();
                        }
                    }
                }
         
                /// <summary>Search <paramref name="inputSpan"/> starting from base.runtextpos for the next location a match could possibly start.</summary>
                /// <param name="inputSpan">The text being scanned by the regular expression.</param>
                /// <returns>true if a possible match was found; false if no more matches are possible.</returns>
                private bool TryFindNextPossibleStartingPosition(ReadOnlySpan<char> inputSpan)
                {
                    int pos = base.runtextpos;
                    ulong charMinusLow;
                     
                    // Any possible match is at least 3 characters.
                    if (pos <= inputSpan.Length - 3)
                    {
                        // The pattern matches a character in the set [CFcf] at index 2.
                        // Find the next occurrence. If it can't be found, there's no match.
                        ReadOnlySpan<char> span = inputSpan.Slice(pos);
                        for (int i = 0; i < span.Length - 2; i++)
                        {
                            int indexOfPos = span.Slice(i + 2).IndexOfAny("CFcf");
                            if (indexOfPos < 0)
                            {
                                goto NoMatchFound;
                            }
                            i += indexOfPos;
                             
                            if (((long)((0x9000000090000000UL << (int)(charMinusLow = (uint)span[i] - 'A')) & (charMinusLow - 64)) < 0) &&
                                ((long)((0x9000000090000000UL << (int)(charMinusLow = (uint)span[i + 1] - 'B')) & (charMinusLow - 64)) < 0))
                            {
                                base.runtextpos = pos + i;
                                return true;
                            }
                        }
                    }
                     
                    // No match found.
                    NoMatchFound:
                    base.runtextpos = inputSpan.Length;
                    return false;
                }
         
                /// <summary>Determine whether <paramref name="inputSpan"/> at base.runtextpos is a match for the regular expression.</summary>
                /// <param name="inputSpan">The text being scanned by the regular expression.</param>
                /// <returns>true if the regular expression matches at the current position; otherwise, false.</returns>
                private bool TryMatchAtCurrentPosition(ReadOnlySpan<char> inputSpan)
                {
                    int pos = base.runtextpos;
                    int matchStart = pos;
                    ReadOnlySpan<char> slice = inputSpan.Slice(pos);
                     
                    // Match with 2 alternative expressions, atomically.
                    {
                        if (slice.IsEmpty)
                        {
                            return false; // The input didn't match.
                        }
                         
                        switch (slice[0])
                        {
                            case 'A' or 'a':
                                if ((uint)slice.Length < 3 ||
                                    !slice.Slice(1).StartsWith("bc", StringComparison.OrdinalIgnoreCase)) // Match the string "bc" (ordinal case-insensitive)
                                {
                                    return false; // The input didn't match.
                                }
                                 
                                pos += 3;
                                slice = inputSpan.Slice(pos);
                                break;
                                 
                            case 'D' or 'd':
                                if ((uint)slice.Length < 3 ||
                                    !slice.Slice(1).StartsWith("ef", StringComparison.OrdinalIgnoreCase)) // Match the string "ef" (ordinal case-insensitive)
                                {
                                    return false; // The input didn't match.
                                }
                                 
                                pos += 3;
                                slice = inputSpan.Slice(pos);
                                break;
                                 
                            default:
                                return false; // The input didn't match.
                        }
                    }
                     
                    // The input matched.
                    base.runtextpos = pos;
                    base.Capture(0, matchStart, pos);
                    return true;
                }
            }
        }
 
    }
     
    /// <summary>Helper methods used by generated <see cref="Regex"/>-derived implementations.</summary>
    [GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "7.0.8.17405")]
    file static class Utilities
    {
        /// <summary>Default timeout value set in <see cref="AppContext"/>, or <see cref="Regex.InfiniteMatchTimeout"/> if none was set.</summary>
        internal static readonly TimeSpan s_defaultTimeout = AppContext.GetData("REGEX_DEFAULT_MATCH_TIMEOUT") is TimeSpan timeout ? timeout : Regex.InfiniteMatchTimeout;
         
        /// <summary>Whether <see cref="s_defaultTimeout"/> is non-infinite.</summary>
        internal static readonly bool s_hasTimeout = s_defaultTimeout != Timeout.InfiniteTimeSpan;
    }
}

Code and pdf at

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

RSCG – RSCG_Utils

RSCG – RSCG_Utils
 
 

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

Add files as C# consts

 

This is how you can use RSCG_Utils .

The code that you start with is

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<Project Sdk="Microsoft.NET.Sdk">
 
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
 
  <ItemGroup>
    <PackageReference Include="rscgutils" Version="2023.514.835" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
   
  </ItemGroup>
    <ItemGroup>
        <AdditionalFiles Include="data.gen.txt" />
    </ItemGroup>
 
    <PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
    </PropertyGroup>
 
 
</Project>

The code that you will use is

1
2
3
Console.WriteLine("Hello, World!");
string dataFromFile = MyAdditionalFiles.data_gen_txt;
Console.Write(dataFromFile);
1
2
3
This is a data
That you will retrieve
as C# const

 

The code that is generated is

1
2
3
4
5
6
7
8
9
    public static partial class MyAdditionalFiles
    {
        public const string data_gen_txt =  """"""""""
This is a data
That you will retrieve
as C# const
"""""""""";
    }

Code and pdf at

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

RSCG – System.Text.Json

 
 

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

Json Serialize without reflection

 

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

The code that you start with is

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<Project Sdk="Microsoft.NET.Sdk">
 
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
    <PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
    </PropertyGroup>
 
</Project>

The code that you will use is

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using JsonSerializerOptionsExample;
using System.Text.Json;
//for asp.net core
//services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.AddContext<MyJsonContext>());
 
string jsonString ="""
{
  "date": "2019-08-01T00:00:00",
  "temperatureCelsius": 25,
  "summary": "Hot"
}
""";
        WeatherForecast? weatherForecast= JsonSerializer.Deserialize(
            jsonString,
            typeof(WeatherForecast),
            new OptionsExampleContext(
                new JsonSerializerOptions(JsonSerializerDefaults.Web)))
                as WeatherForecast;
        Console.WriteLine($"Date={weatherForecast?.Date}");
        // output:
        //Date=8/1/2019 12:00:00 AM
 
        jsonString = JsonSerializer.Serialize(
            weatherForecast,
            typeof(WeatherForecast),
            new OptionsExampleContext(
                new JsonSerializerOptions(JsonSerializerDefaults.Web)));
        Console.WriteLine(jsonString);
jsonString = JsonSerializer.Serialize(
    weatherForecast,
    typeof(WeatherForecast),
    new OptionsExampleContext(
        new JsonSerializerOptions(JsonSerializerDefaults.General)));
Console.WriteLine(jsonString);
// output:
//{ "date":"2019-08-01T00:00:00","temperatureCelsius":25,"summary":"Hot"}
1
2
3
4
5
6
7
8
namespace JsonSerializerOptionsExample;
 
public class WeatherForecast
{
    public DateTime Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
}
1
2
3
4
5
6
7
8
using System.Text.Json.Serialization;
 
namespace JsonSerializerOptionsExample;
 
[JsonSerializable(typeof(WeatherForecast))]
internal partial class OptionsExampleContext : JsonSerializerContext
{
}

 

The code that is generated is

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// <auto-generated/>
 
#nullable enable annotations
#nullable disable warnings
 
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
 
namespace JsonSerializerOptionsExample
{
    internal partial class OptionsExampleContext
    {
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.DateTime>? _DateTime;
        /// <summary>
        /// Defines the source generated JSON serialization contract metadata for a given type.
        /// </summary>
        public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.DateTime> DateTime
        {
            get => _DateTime ??= Create_DateTime(Options, makeReadOnly: true);
        }
         
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.DateTime> Create_DateTime(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
        {
            global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.DateTime>? jsonTypeInfo = null;
            global::System.Text.Json.Serialization.JsonConverter? customConverter;
            if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::System.DateTime))) != null)
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.DateTime>(options, customConverter);
            }
            else
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.DateTime>(options, global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.DateTimeConverter);
            }
         
            if (makeReadOnly)
            {
                jsonTypeInfo.MakeReadOnly();
            }
         
            return jsonTypeInfo;
        }
         
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// <auto-generated/>
 
#nullable enable annotations
#nullable disable warnings
 
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
 
namespace JsonSerializerOptionsExample
{
     
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "7.0.8.17405")]
    internal partial class OptionsExampleContext
    {
         
        private static global::System.Text.Json.JsonSerializerOptions s_defaultOptions { get; } = new global::System.Text.Json.JsonSerializerOptions()
        {
            DefaultIgnoreCondition = global::System.Text.Json.Serialization.JsonIgnoreCondition.Never,
            IgnoreReadOnlyFields = false,
            IgnoreReadOnlyProperties = false,
            IncludeFields = false,
            WriteIndented = false,
        };
         
        private static global::JsonSerializerOptionsExample.OptionsExampleContext? s_defaultContext;
         
        /// <summary>
        /// The default <see cref="global::System.Text.Json.Serialization.JsonSerializerContext"/> associated with a default <see cref="global::System.Text.Json.JsonSerializerOptions"/> instance.
        /// </summary>
        public static global::JsonSerializerOptionsExample.OptionsExampleContext Default => s_defaultContext ??= new global::JsonSerializerOptionsExample.OptionsExampleContext(new global::System.Text.Json.JsonSerializerOptions(s_defaultOptions));
         
        /// <summary>
        /// The source-generated options associated with this context.
        /// </summary>
        protected override global::System.Text.Json.JsonSerializerOptions? GeneratedSerializerOptions { get; } = s_defaultOptions;
         
        /// <inheritdoc/>
        public OptionsExampleContext() : base(null)
        {
        }
         
        /// <inheritdoc/>
        public OptionsExampleContext(global::System.Text.Json.JsonSerializerOptions options) : base(options)
        {
        }
         
        private static global::System.Text.Json.Serialization.JsonConverter? GetRuntimeProvidedCustomConverter(global::System.Text.Json.JsonSerializerOptions options, global::System.Type type)
        {
            global::System.Collections.Generic.IList<global::System.Text.Json.Serialization.JsonConverter> converters = options.Converters;
         
            for (int i = 0; i < converters.Count; i++)
            {
                global::System.Text.Json.Serialization.JsonConverter? converter = converters[i];
         
                if (converter.CanConvert(type))
                {
                    if (converter is global::System.Text.Json.Serialization.JsonConverterFactory factory)
                    {
                        converter = factory.CreateConverter(type, options);
                        if (converter == null || converter is global::System.Text.Json.Serialization.JsonConverterFactory)
                        {
                            throw new global::System.InvalidOperationException(string.Format("The converter '{0}' cannot return null or a JsonConverterFactory instance.", factory.GetType()));
                        }
                    }
         
                    return converter;
                }
            }
         
            return null;
        }
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// <auto-generated/>
 
#nullable enable annotations
#nullable disable warnings
 
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
 
namespace JsonSerializerOptionsExample
{
    internal partial class OptionsExampleContext: global::System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver
    {
        /// <inheritdoc/>
        public override global::System.Text.Json.Serialization.Metadata.JsonTypeInfo GetTypeInfo(global::System.Type type)
        {
            if (type == typeof(global::JsonSerializerOptionsExample.WeatherForecast))
            {
                return this.WeatherForecast;
            }
         
            if (type == typeof(global::System.DateTime))
            {
                return this.DateTime;
            }
         
            if (type == typeof(global::System.Int32))
            {
                return this.Int32;
            }
         
            if (type == typeof(global::System.String))
            {
                return this.String;
            }
         
            return null!;
        }
         
        global::System.Text.Json.Serialization.Metadata.JsonTypeInfo? global::System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver.GetTypeInfo(global::System.Type type, global::System.Text.Json.JsonSerializerOptions options)
        {
            if (type == typeof(global::JsonSerializerOptionsExample.WeatherForecast))
            {
                return Create_WeatherForecast(options, makeReadOnly: false);
            }
         
            if (type == typeof(global::System.DateTime))
            {
                return Create_DateTime(options, makeReadOnly: false);
            }
         
            if (type == typeof(global::System.Int32))
            {
                return Create_Int32(options, makeReadOnly: false);
            }
         
            if (type == typeof(global::System.String))
            {
                return Create_String(options, makeReadOnly: false);
            }
         
            return null;
        }
         
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// <auto-generated/>
 
#nullable enable annotations
#nullable disable warnings
 
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
 
namespace JsonSerializerOptionsExample
{
    internal partial class OptionsExampleContext
    {
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Int32>? _Int32;
        /// <summary>
        /// Defines the source generated JSON serialization contract metadata for a given type.
        /// </summary>
        public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Int32> Int32
        {
            get => _Int32 ??= Create_Int32(Options, makeReadOnly: true);
        }
         
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Int32> Create_Int32(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
        {
            global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Int32>? jsonTypeInfo = null;
            global::System.Text.Json.Serialization.JsonConverter? customConverter;
            if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::System.Int32))) != null)
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.Int32>(options, customConverter);
            }
            else
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.Int32>(options, global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.Int32Converter);
            }
         
            if (makeReadOnly)
            {
                jsonTypeInfo.MakeReadOnly();
            }
         
            return jsonTypeInfo;
        }
         
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
// <auto-generated/>
 
#nullable enable annotations
#nullable disable warnings
 
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
 
namespace JsonSerializerOptionsExample
{
    internal partial class OptionsExampleContext
    {
         
        private static readonly global::System.Text.Json.JsonEncodedText PropName_Date = global::System.Text.Json.JsonEncodedText.Encode("Date");
        private static readonly global::System.Text.Json.JsonEncodedText PropName_TemperatureCelsius = global::System.Text.Json.JsonEncodedText.Encode("TemperatureCelsius");
        private static readonly global::System.Text.Json.JsonEncodedText PropName_Summary = global::System.Text.Json.JsonEncodedText.Encode("Summary");
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// <auto-generated/>
 
#nullable enable annotations
#nullable disable warnings
 
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
 
namespace JsonSerializerOptionsExample
{
    internal partial class OptionsExampleContext
    {
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.String>? _String;
        /// <summary>
        /// Defines the source generated JSON serialization contract metadata for a given type.
        /// </summary>
        public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.String> String
        {
            get => _String ??= Create_String(Options, makeReadOnly: true);
        }
         
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.String> Create_String(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
        {
            global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.String>? jsonTypeInfo = null;
            global::System.Text.Json.Serialization.JsonConverter? customConverter;
            if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::System.String))) != null)
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.String>(options, customConverter);
            }
            else
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.String>(options, global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.StringConverter);
            }
         
            if (makeReadOnly)
            {
                jsonTypeInfo.MakeReadOnly();
            }
         
            return jsonTypeInfo;
        }
         
    }
}
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// <auto-generated/>
 
#nullable enable annotations
#nullable disable warnings
 
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
 
namespace JsonSerializerOptionsExample
{
    internal partial class OptionsExampleContext
    {
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonSerializerOptionsExample.WeatherForecast>? _WeatherForecast;
        /// <summary>
        /// Defines the source generated JSON serialization contract metadata for a given type.
        /// </summary>
        public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonSerializerOptionsExample.WeatherForecast> WeatherForecast
        {
            get => _WeatherForecast ??= Create_WeatherForecast(Options, makeReadOnly: true);
        }
         
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonSerializerOptionsExample.WeatherForecast> Create_WeatherForecast(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
        {
            global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonSerializerOptionsExample.WeatherForecast>? jsonTypeInfo = null;
            global::System.Text.Json.Serialization.JsonConverter? customConverter;
            if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::JsonSerializerOptionsExample.WeatherForecast))) != null)
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::JsonSerializerOptionsExample.WeatherForecast>(options, customConverter);
            }
            else
            {
                global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::JsonSerializerOptionsExample.WeatherForecast> objectInfo = new global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::JsonSerializerOptionsExample.WeatherForecast>()
                {
                    ObjectCreator = static () => new global::JsonSerializerOptionsExample.WeatherForecast(),
                    ObjectWithParameterizedConstructorCreator = null,
                    PropertyMetadataInitializer = _ => WeatherForecastPropInit(options),
                    ConstructorParameterMetadataInitializer = null,
                    NumberHandling = default,
                    SerializeHandler = WeatherForecastSerializeHandler
                };
         
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateObjectInfo<global::JsonSerializerOptionsExample.WeatherForecast>(options, objectInfo);
            }
         
            if (makeReadOnly)
            {
                jsonTypeInfo.MakeReadOnly();
            }
         
            return jsonTypeInfo;
        }
         
        private static global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] WeatherForecastPropInit(global::System.Text.Json.JsonSerializerOptions options)
        {
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] properties = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[3];
         
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.DateTime> info0 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.DateTime>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::JsonSerializerOptionsExample.WeatherForecast),
                Converter = null,
                Getter = static (obj) => ((global::JsonSerializerOptionsExample.WeatherForecast)obj).Date,
                Setter = static (obj, value) => ((global::JsonSerializerOptionsExample.WeatherForecast)obj).Date = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "Date",
                JsonPropertyName = null
            };
         
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo0 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.DateTime>(options, info0);
            properties[0] = propertyInfo0;
         
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Int32> info1 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Int32>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::JsonSerializerOptionsExample.WeatherForecast),
                Converter = null,
                Getter = static (obj) => ((global::JsonSerializerOptionsExample.WeatherForecast)obj).TemperatureCelsius,
                Setter = static (obj, value) => ((global::JsonSerializerOptionsExample.WeatherForecast)obj).TemperatureCelsius = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "TemperatureCelsius",
                JsonPropertyName = null
            };
         
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo1 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.Int32>(options, info1);
            properties[1] = propertyInfo1;
         
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String> info2 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::JsonSerializerOptionsExample.WeatherForecast),
                Converter = null,
                Getter = static (obj) => ((global::JsonSerializerOptionsExample.WeatherForecast)obj).Summary!,
                Setter = static (obj, value) => ((global::JsonSerializerOptionsExample.WeatherForecast)obj).Summary = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "Summary",
                JsonPropertyName = null
            };
         
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo2 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.String>(options, info2);
            properties[2] = propertyInfo2;
         
            return properties;
        }
         
        // Intentionally not a static method because we create a delegate to it. Invoking delegates to instance
        // methods is almost as fast as virtual calls. Static methods need to go through a shuffle thunk.
        private void WeatherForecastSerializeHandler(global::System.Text.Json.Utf8JsonWriter writer, global::JsonSerializerOptionsExample.WeatherForecast? value)
        {
            if (value == null)
            {
                writer.WriteNullValue();
                return;
            }
         
            writer.WriteStartObject();
            writer.WriteString(PropName_Date, value.Date);
            writer.WriteNumber(PropName_TemperatureCelsius, value.TemperatureCelsius);
            writer.WriteString(PropName_Summary, value.Summary);
         
            writer.WriteEndObject();
        }
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// <auto-generated/>
 
#nullable enable annotations
#nullable disable warnings
 
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
 
namespace BothModesNoOptions
{
     
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "7.0.8.17405")]
    internal partial class SourceGenerationContext
    {
         
        private static global::System.Text.Json.JsonSerializerOptions s_defaultOptions { get; } = new global::System.Text.Json.JsonSerializerOptions()
        {
            DefaultIgnoreCondition = global::System.Text.Json.Serialization.JsonIgnoreCondition.Never,
            IgnoreReadOnlyFields = false,
            IgnoreReadOnlyProperties = false,
            IncludeFields = false,
            WriteIndented = true,
        };
         
        private static global::BothModesNoOptions.SourceGenerationContext? s_defaultContext;
         
        /// <summary>
        /// The default <see cref="global::System.Text.Json.Serialization.JsonSerializerContext"/> associated with a default <see cref="global::System.Text.Json.JsonSerializerOptions"/> instance.
        /// </summary>
        public static global::BothModesNoOptions.SourceGenerationContext Default => s_defaultContext ??= new global::BothModesNoOptions.SourceGenerationContext(new global::System.Text.Json.JsonSerializerOptions(s_defaultOptions));
         
        /// <summary>
        /// The source-generated options associated with this context.
        /// </summary>
        protected override global::System.Text.Json.JsonSerializerOptions? GeneratedSerializerOptions { get; } = s_defaultOptions;
         
        /// <inheritdoc/>
        public SourceGenerationContext() : base(null)
        {
        }
         
        /// <inheritdoc/>
        public SourceGenerationContext(global::System.Text.Json.JsonSerializerOptions options) : base(options)
        {
        }
         
        private static global::System.Text.Json.Serialization.JsonConverter? GetRuntimeProvidedCustomConverter(global::System.Text.Json.JsonSerializerOptions options, global::System.Type type)
        {
            global::System.Collections.Generic.IList<global::System.Text.Json.Serialization.JsonConverter> converters = options.Converters;
         
            for (int i = 0; i < converters.Count; i++)
            {
                global::System.Text.Json.Serialization.JsonConverter? converter = converters[i];
         
                if (converter.CanConvert(type))
                {
                    if (converter is global::System.Text.Json.Serialization.JsonConverterFactory factory)
                    {
                        converter = factory.CreateConverter(type, options);
                        if (converter == null || converter is global::System.Text.Json.Serialization.JsonConverterFactory)
                        {
                            throw new global::System.InvalidOperationException(string.Format("The converter '{0}' cannot return null or a JsonConverterFactory instance.", factory.GetType()));
                        }
                    }
         
                    return converter;
                }
            }
         
            return null;
        }
    }
}
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// <auto-generated/>
#nullable enable
#pragma warning disable CS0162 // Unreachable code
#pragma warning disable CS0164 // Unreferenced label
#pragma warning disable CS0219 // Variable assigned but never used
 
namespace JsonSerializerOptionsExample
{
    partial class WeatherForecast
    {
        /// <remarks>
        /// Pattern explanation:<br/>
        /// <code>
        /// ○ Match with 2 alternative expressions, atomically.<br/>
        ///     ○ Match a sequence of expressions.<br/>
        ///         ○ Match a character in the set [Aa].<br/>
        ///         ○ Match a character in the set [Bb].<br/>
        ///         ○ Match a character in the set [Cc].<br/>
        ///     ○ Match a sequence of expressions.<br/>
        ///         ○ Match a character in the set [Dd].<br/>
        ///         ○ Match a character in the set [Ee].<br/>
        ///         ○ Match a character in the set [Ff].<br/>
        /// </code>
        /// </remarks>
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "7.0.8.17405")]
        private static partial global::System.Text.RegularExpressions.Regex AbcOrDefGeneratedRegex() => global::System.Text.RegularExpressions.Generated.AbcOrDefGeneratedRegex_0.Instance;
    }
}
 
namespace System.Text.RegularExpressions.Generated
{
    using System;
    using System.CodeDom.Compiler;
    using System.Collections;
    using System.ComponentModel;
    using System.Globalization;
    using System.Runtime.CompilerServices;
    using System.Text.RegularExpressions;
    using System.Threading;
 
    /// <summary>Custom <see cref="Regex"/>-derived type for the AbcOrDefGeneratedRegex method.</summary>
    [GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "7.0.8.17405")]
    file sealed class AbcOrDefGeneratedRegex_0 : Regex
    {
        /// <summary>Cached, thread-safe singleton instance.</summary>
        internal static readonly AbcOrDefGeneratedRegex_0 Instance = new();
     
        /// <summary>Initializes the instance.</summary>
        private AbcOrDefGeneratedRegex_0()
        {
            base.pattern = "abc|def";
            base.roptions = RegexOptions.IgnoreCase;
            ValidateMatchTimeout(Utilities.s_defaultTimeout);
            base.internalMatchTimeout = Utilities.s_defaultTimeout;
            base.factory = new RunnerFactory();
            base.capsize = 1;
        }
     
        /// <summary>Provides a factory for creating <see cref="RegexRunner"/> instances to be used by methods on <see cref="Regex"/>.</summary>
        private sealed class RunnerFactory : RegexRunnerFactory
        {
            /// <summary>Creates an instance of a <see cref="RegexRunner"/> used by methods on <see cref="Regex"/>.</summary>
            protected override RegexRunner CreateInstance() => new Runner();
         
            /// <summary>Provides the runner that contains the custom logic implementing the specified regular expression.</summary>
            private sealed class Runner : RegexRunner
            {
                /// <summary>Scan the <paramref name="inputSpan"/> starting from base.runtextstart for the next match.</summary>
                /// <param name="inputSpan">The text being scanned by the regular expression.</param>
                protected override void Scan(ReadOnlySpan<char> inputSpan)
                {
                    // Search until we can't find a valid starting position, we find a match, or we reach the end of the input.
                    while (TryFindNextPossibleStartingPosition(inputSpan) &&
                           !TryMatchAtCurrentPosition(inputSpan) &&
                           base.runtextpos != inputSpan.Length)
                    {
                        base.runtextpos++;
                        if (Utilities.s_hasTimeout)
                        {
                            base.CheckTimeout();
                        }
                    }
                }
         
                /// <summary>Search <paramref name="inputSpan"/> starting from base.runtextpos for the next location a match could possibly start.</summary>
                /// <param name="inputSpan">The text being scanned by the regular expression.</param>
                /// <returns>true if a possible match was found; false if no more matches are possible.</returns>
                private bool TryFindNextPossibleStartingPosition(ReadOnlySpan<char> inputSpan)
                {
                    int pos = base.runtextpos;
                    ulong charMinusLow;
                     
                    // Any possible match is at least 3 characters.
                    if (pos <= inputSpan.Length - 3)
                    {
                        // The pattern matches a character in the set [CFcf] at index 2.
                        // Find the next occurrence. If it can't be found, there's no match.
                        ReadOnlySpan<char> span = inputSpan.Slice(pos);
                        for (int i = 0; i < span.Length - 2; i++)
                        {
                            int indexOfPos = span.Slice(i + 2).IndexOfAny("CFcf");
                            if (indexOfPos < 0)
                            {
                                goto NoMatchFound;
                            }
                            i += indexOfPos;
                             
                            if (((long)((0x9000000090000000UL << (int)(charMinusLow = (uint)span[i] - 'A')) & (charMinusLow - 64)) < 0) &&
                                ((long)((0x9000000090000000UL << (int)(charMinusLow = (uint)span[i + 1] - 'B')) & (charMinusLow - 64)) < 0))
                            {
                                base.runtextpos = pos + i;
                                return true;
                            }
                        }
                    }
                     
                    // No match found.
                    NoMatchFound:
                    base.runtextpos = inputSpan.Length;
                    return false;
                }
         
                /// <summary>Determine whether <paramref name="inputSpan"/> at base.runtextpos is a match for the regular expression.</summary>
                /// <param name="inputSpan">The text being scanned by the regular expression.</param>
                /// <returns>true if the regular expression matches at the current position; otherwise, false.</returns>
                private bool TryMatchAtCurrentPosition(ReadOnlySpan<char> inputSpan)
                {
                    int pos = base.runtextpos;
                    int matchStart = pos;
                    ReadOnlySpan<char> slice = inputSpan.Slice(pos);
                     
                    // Match with 2 alternative expressions, atomically.
                    {
                        if (slice.IsEmpty)
                        {
                            return false; // The input didn't match.
                        }
                         
                        switch (slice[0])
                        {
                            case 'A' or 'a':
                                if ((uint)slice.Length < 3 ||
                                    !slice.Slice(1).StartsWith("bc", StringComparison.OrdinalIgnoreCase)) // Match the string "bc" (ordinal case-insensitive)
                                {
                                    return false; // The input didn't match.
                                }
                                 
                                pos += 3;
                                slice = inputSpan.Slice(pos);
                                break;
                                 
                            case 'D' or 'd':
                                if ((uint)slice.Length < 3 ||
                                    !slice.Slice(1).StartsWith("ef", StringComparison.OrdinalIgnoreCase)) // Match the string "ef" (ordinal case-insensitive)
                                {
                                    return false; // The input didn't match.
                                }
                                 
                                pos += 3;
                                slice = inputSpan.Slice(pos);
                                break;
                                 
                            default:
                                return false; // The input didn't match.
                        }
                    }
                     
                    // The input matched.
                    base.runtextpos = pos;
                    base.Capture(0, matchStart, pos);
                    return true;
                }
            }
        }
 
    }
     
    /// <summary>Helper methods used by generated <see cref="Regex"/>-derived implementations.</summary>
    [GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "7.0.8.17405")]
    file static class Utilities
    {
        /// <summary>Default timeout value set in <see cref="AppContext"/>, or <see cref="Regex.InfiniteMatchTimeout"/> if none was set.</summary>
        internal static readonly TimeSpan s_defaultTimeout = AppContext.GetData("REGEX_DEFAULT_MATCH_TIMEOUT") is TimeSpan timeout ? timeout : Regex.InfiniteMatchTimeout;
         
        /// <summary>Whether <see cref="s_defaultTimeout"/> is non-infinite.</summary>
        internal static readonly bool s_hasTimeout = s_defaultTimeout != Timeout.InfiniteTimeSpan;
    }
}

Code and pdf at

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

RSCG – RSCG_TimeBombComment

 
 

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

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

 

This is how you can use RSCG_TimeBombComment .

The code that you start with is

01
02
03
04
05
06
07
08
09
10
11
12
13
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net7.0</TargetFramework>
    </PropertyGroup>
    <PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="RSCG_TimeBombComment" Version="2023.5.9.2110" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
    </ItemGroup>
</Project>

The code that you will use is

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
namespace Console_TimeBombComment;
internal partial class TestClass
{
    [Obsolete("this will be obsolete",TB_20230508)]
    public int DataObsolete()
    {
        return 5;
    }
 
    public int CommentsWithErrors()
    {
        //JFD: test
        //TB: 2021-09-13 this is a comment transformed into an error
        //TB: and this is a warning
        //TB: 2050-12-30 and this should not appear yet
        return 5;
    }
}

 

The code that is generated is

1
2
3
4
5
6
7
namespace Console_TimeBombComment {
    partial class TestClass {
        const bool TB_20230508 = true;
    }
}
 
                

Code and pdf at

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

RSCG – ThisAssembly

RSCG – ThisAssembly
 
 

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

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

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

 

This is how you can use ThisAssembly .

The code that you start with is

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp7.0</TargetFramework>
    </PropertyGroup>
    <PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedX</CompilerGeneratedFilesOutputPath>
    </PropertyGroup>
    <PropertyGroup>
        <Version>2023.5.7.800</Version>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="ThisAssembly" Version="1.2.14" OutputItemType="Analyzer" ReferenceOutputAssembly="false">
            <PrivateAssets>all</PrivateAssets>
            <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
        </PackageReference>
    </ItemGroup>
</Project>

The code that you will use is

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

 

The code that is generated is

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
 
using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;
 
/// <summary>
/// Provides access to the current assembly information as pure constants,
///  without requiring reflection.
/// </summary>
partial class ThisAssembly
{
    /// <summary>
    /// Gets the AssemblyInfo attributes.
    /// </summary>
    [GeneratedCode("ThisAssembly.AssemblyInfo", "1.2.14")]
    [CompilerGenerated]
    public static partial class Info
    {
        public const string Company = @"RSCG_Version";
 
        public const string Configuration = @"Debug";
 
        public const string FileVersion = @"2023.5.7.800";
 
        public const string InformationalVersion = @"2023.5.7.800";
 
        public const string Product = @"RSCG_Version";
 
        public const string Title = @"RSCG_Version";
 
        public const string Version = @"2023.5.7.800";
 
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;
 
partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Branch = @"[pending build]";
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;
 
partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Commit = @"[pending build]";
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;
 
partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Root = @"[pending build]";
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;
 
partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Sha = @"[pending build]";
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     ThisAssembly.Constants: 1.2.14
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Globalization;
 
partial class ThisAssembly
{
    public static partial class Git
    {
        /// <summary>
        /// => @"[pending build]"
        /// </summary>
        public const string Url = @"[pending build]";
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
 
using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;
 
/// <summary>
/// Provides access to the current assembly information as pure constants,
///  without requiring reflection.
/// </summary>
partial class ThisAssembly
{
    /// <summary>
    /// Gets the assembly metadata.
    /// </summary>
    [GeneratedCode("ThisAssembly.Metadata", "1.2.14")]
    [CompilerGenerated]
    public static partial class Metadata
    {
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
 
using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;
 
/// <summary>
/// Provides access to the current assembly information as pure constants,
///  without requiring reflection.
/// </summary>
partial class ThisAssembly
{
    /// <summary>
    /// Gets the project properties.
    /// </summary>
    [GeneratedCode("ThisAssembly.Project", "1.2.14")]
    [CompilerGenerated]
    public static partial class Project
    {
        /// <summary>AssemblyName = RSCG_Version</summary>
        public const string AssemblyName = @"RSCG_Version";
 
        /// <summary>RootNamespace = RSCG_Version</summary>
        public const string RootNamespace = @"RSCG_Version";
 
        /// <summary>TargetFrameworkIdentifier = .NETCoreApp</summary>
        public const string TargetFrameworkIdentifier = @".NETCoreApp";
 
        /// <summary>TargetFrameworkMoniker = .NETCoreApp,Version=v7.0</summary>
        public const string TargetFrameworkMoniker = @".NETCoreApp,Version=v7.0";
 
        /// <summary>TargetFrameworkVersion = v7.0</summary>
        public const string TargetFrameworkVersion = @"v7.0";
 
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using System;
using System.IO;
using System.Linq;
using System.Reflection;
 
static class EmbeddedResource
{
    static readonly string baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "";
 
    public static string GetContent(string relativePath)
    {
        using var stream = GetStream(relativePath);
        using var reader = new StreamReader(stream);
        return reader.ReadToEnd();
    }
 
    public static byte[] GetBytes(string relativePath)
    {
        using var stream = GetStream(relativePath);
        var bytes = new byte[stream.Length];
        stream.Read(bytes, 0, bytes.Length);
        return bytes;
    }
 
    public static Stream GetStream(string relativePath)
    {
        var filePath = Path.Combine(baseDir, Path.GetFileName(relativePath));
        if (File.Exists(filePath))
            return File.OpenRead(filePath);
 
        var baseName = Assembly.GetExecutingAssembly().GetName().Name;
        var resourceName = relativePath
            .TrimStart('.')
            .Replace('/', '.')
            .Replace('\\', '.');
 
        var manifestResourceName = Assembly.GetExecutingAssembly()
            .GetManifestResourceNames().FirstOrDefault(x => x.EndsWith(resourceName));
 
        if (string.IsNullOrEmpty(manifestResourceName))
            throw new InvalidOperationException($"Did not find required resource ending in '{resourceName}' in assembly '{baseName}'.");
 
        return
            Assembly.GetExecutingAssembly().GetManifestResourceStream(manifestResourceName) ??
            throw new InvalidOperationException($"Did not find required resource '{manifestResourceName}' in assembly '{baseName}'.");
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
using System.Collections.Concurrent;
using System.Resources;
using System.Runtime.CompilerServices;
 
/// <summary>
/// Provides access to the current assembly information as pure constants,
///  without requiring reflection.
/// </summary>
partial class ThisAssembly
{
    /// <summary>
    /// Access the strings provided by resource files in the project.
    /// </summary>
    [CompilerGenerated]
    public static partial class Strings
    {
        static ConcurrentDictionary<string, ResourceManager> resourceManagers = new ConcurrentDictionary<string, ResourceManager>();
 
        static ResourceManager GetResourceManager(string resourceName)
            => resourceManagers.GetOrAdd(resourceName, name => new ResourceManager(name, typeof(Strings).Assembly));
    }
}

Code and pdf at

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

RSCG–ISourceGenerator porting to IIncrementalGenerator in 3 steps

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

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

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

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

 

There are some problems

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

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

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

 

 

Andrei Ignat weekly software news(mostly .NET)

* indicates required

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

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

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