Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use RegEx source generators on .NET 7 or later #625

Merged
merged 1 commit into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
</PropertyGroup>

<PropertyGroup>
<WarningsAsErrors>$(WarningsAsErrors),SYSLIB1045</WarningsAsErrors>
<WarningsAsErrors>$(WarningsAsErrors),IL2026,IL2060,IL2091,IL2095,IL3050</WarningsAsErrors>
</PropertyGroup>

Expand Down
43 changes: 36 additions & 7 deletions src/Tingle.EventBus/DependencyInjection/EventBusNamingOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@ namespace Microsoft.Extensions.DependencyInjection;
/// <summary>
/// Specifies options for naming behaviour and requirements.
/// </summary>
public class EventBusNamingOptions
public partial class EventBusNamingOptions
{
private static readonly Regex trimPattern = new("(Event|Consumer|EventConsumer)$", RegexOptions.Compiled);
private static readonly Regex namePattern = new("(?<=[a-z0-9])[A-Z]", RegexOptions.Compiled);
private static readonly Regex replacePatternKebabCase = new("[^a-zA-Z0-9-]", RegexOptions.Compiled);
private static readonly Regex replacePatternSnakeCase = new("[^a-zA-Z0-9_]", RegexOptions.Compiled);
private static readonly Regex replacePatternDotCase = new("[^a-zA-Z0-9\\.]", RegexOptions.Compiled);
private static readonly Regex replacePatternDefault = new("[^a-zA-Z0-9-_\\.]", RegexOptions.Compiled);
private const string TrimPattern = "(Event|Consumer|EventConsumer)$";
private const string NamePattern = "(?<=[a-z0-9])[A-Z]";
private const string ReplacePatternKebabCase = "[^a-zA-Z0-9-]";
private const string ReplacePatternSnakeCase = "[^a-zA-Z0-9_]";
private const string ReplacePatternDotCase = "[^a-zA-Z0-9\\.]";
private const string ReplacePatternDefault = "[^a-zA-Z0-9-_\\.]";

private static readonly Regex trimPattern = GetTrimPattern();
private static readonly Regex namePattern = GetNamePattern();
private static readonly Regex replacePatternKebabCase = GetReplacePatternKebabCase();
private static readonly Regex replacePatternSnakeCase = GetReplacePatternSnakeCase();
private static readonly Regex replacePatternDotCase = GetReplacePatternDotCase();
private static readonly Regex replacePatternDefault = GetReplacePatternDefault();

/// <summary>
/// The scope to use for queues and subscriptions.
Expand Down Expand Up @@ -136,4 +143,26 @@ public string Join(params string[] values)
_ => throw new InvalidOperationException($"'{nameof(NamingConvention)}.{Convention}' does not support joining"),
}).ToLowerInvariant();
}

#if NET7_0_OR_GREATER
[GeneratedRegex(TrimPattern, RegexOptions.Compiled)]
private static partial Regex GetTrimPattern();
[GeneratedRegex(NamePattern, RegexOptions.Compiled)]
private static partial Regex GetNamePattern();
[GeneratedRegex(ReplacePatternKebabCase, RegexOptions.Compiled)]
private static partial Regex GetReplacePatternKebabCase();
[GeneratedRegex(ReplacePatternSnakeCase, RegexOptions.Compiled)]
private static partial Regex GetReplacePatternSnakeCase();
[GeneratedRegex(ReplacePatternDotCase, RegexOptions.Compiled)]
private static partial Regex GetReplacePatternDotCase();
[GeneratedRegex(ReplacePatternDefault, RegexOptions.Compiled)]
private static partial Regex GetReplacePatternDefault();
#else
private static Regex GetTrimPattern() => new(TrimPattern, RegexOptions.Compiled);
private static Regex GetNamePattern() => new(NamePattern, RegexOptions.Compiled);
private static Regex GetReplacePatternKebabCase() => new(ReplacePatternKebabCase, RegexOptions.Compiled);
private static Regex GetReplacePatternSnakeCase() => new(ReplacePatternSnakeCase, RegexOptions.Compiled);
private static Regex GetReplacePatternDotCase() => new(ReplacePatternDotCase, RegexOptions.Compiled);
private static Regex GetReplacePatternDefault() => new(ReplacePatternDefault, RegexOptions.Compiled);
#endif
}
13 changes: 11 additions & 2 deletions src/Tingle.EventBus/Serialization/AbstractEventSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ namespace Tingle.EventBus.Serialization;
/// <summary>
/// Abstract implementation for an event serializer.
/// </summary>
public abstract class AbstractEventSerializer : IEventSerializer
public abstract partial class AbstractEventSerializer : IEventSerializer
{
private const string TrimPattern = "(Serializer|EventSerializer)$";

///
protected static readonly IList<string> JsonContentTypes = new[] { "application/json", "text/json", };

private static readonly Regex trimPattern = new("(Serializer|EventSerializer)$", RegexOptions.Compiled);
private static readonly Regex trimPattern = GetTrimPattern();

/// <summary>
///
Expand Down Expand Up @@ -147,4 +149,11 @@ protected abstract Task SerializeEnvelopeAsync<T>(Stream stream,
EventEnvelope<T> envelope,
CancellationToken cancellationToken = default)
where T : class;

#if NET7_0_OR_GREATER
[GeneratedRegex(TrimPattern, RegexOptions.Compiled)]
private static partial Regex GetTrimPattern();
#else
private static Regex GetTrimPattern() => new(TrimPattern, RegexOptions.Compiled);
#endif
}
15 changes: 12 additions & 3 deletions src/Tingle.EventBus/Transports/EventBusTransport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ namespace Tingle.EventBus.Transports;
/// Abstract implementation for an event bus transport.
/// </summary>
/// <typeparam name="TOptions">The type used for configuring options of the transport</typeparam>
public abstract class EventBusTransport<TOptions> : IEventBusTransport where TOptions : EventBusTransportOptions, new()
public abstract partial class EventBusTransport<TOptions> : IEventBusTransport where TOptions : EventBusTransportOptions, new()
{
private static readonly Regex CategoryNamePattern = new(@"Transport$", RegexOptions.Compiled);
private const string CategoryNamePattern = "Transport$";

private static readonly Regex categoryNamePattern = GetCategoryNamePattern();
private readonly IServiceScopeFactory scopeFactory;
private readonly IOptionsMonitor<TOptions> optionsMonitor;

Expand All @@ -41,7 +43,7 @@ public EventBusTransport(IServiceScopeFactory scopeFactory,

// Create a well-scoped logger
var categoryName = $"{LogCategoryNames.Transports}.{GetType().Name}";
categoryName = CategoryNamePattern.Replace(categoryName, string.Empty); // remove trailing "Transport"
categoryName = categoryNamePattern.Replace(categoryName, string.Empty); // remove trailing "Transport"
Logger = loggerFactory?.CreateLogger(categoryName) ?? throw new ArgumentNullException(nameof(loggerFactory));
}

Expand Down Expand Up @@ -382,5 +384,12 @@ protected async Task<EventConsumeResult> ConsumeAsync(IServiceScope scope,
return Logger.BeginScope(state);
}

#if NET7_0_OR_GREATER
[GeneratedRegex(CategoryNamePattern, RegexOptions.Compiled)]
private static partial Regex GetCategoryNamePattern();
#else
private static Regex GetCategoryNamePattern() => new(CategoryNamePattern, RegexOptions.Compiled);
#endif

#endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@ namespace Microsoft.Extensions.DependencyInjection;
/// <param name="configurationProvider">An <see cref="IEventBusConfigurationProvider"/> instance.</param>
/// <param name="configurators">A list of <see cref="IEventBusConfigurator"/> to use when configuring options.</param>
/// <param name="busOptionsAccessor">An <see cref="IOptions{TOptions}"/> for bus configuration.</param>
public abstract class EventBusTransportConfigureOptions<TOptions>(IEventBusConfigurationProvider configurationProvider,
public abstract partial class EventBusTransportConfigureOptions<TOptions>(IEventBusConfigurationProvider configurationProvider,
IEnumerable<IEventBusConfigurator> configurators,
IOptions<EventBusOptions> busOptionsAccessor) : IConfigureNamedOptions<TOptions>,
IPostConfigureOptions<TOptions>,
IValidateOptions<TOptions>
where TOptions : EventBusTransportOptions
{
private const string ReplacePatternSafeEnv = "[^a-zA-Z0-9_]";

// Some hosts do not allow certain characters for ENV vars but we know they all support alphanumeric and underscore
// For example, Azure Container Instances does not allow hyphens in ENV vars while Azure Container Apps does
private static readonly Regex replacePatternSafeEnv = new("[^a-zA-Z0-9_]", RegexOptions.Compiled);
private static readonly Regex replacePatternSafeEnv = GetReplacePatternSafeEnv();

private readonly IEventBusConfigurationProvider configurationProvider = configurationProvider ?? throw new ArgumentNullException(nameof(configurationProvider));
private readonly IEnumerable<IEventBusConfigurator> configurators = configurators ?? throw new ArgumentNullException(nameof(configurators));
Expand Down Expand Up @@ -98,4 +100,11 @@ public virtual ValidateOptionsResult Validate(string? name, TOptions options)

return ValidateOptionsResult.Success;
}

#if NET7_0_OR_GREATER
[GeneratedRegex(ReplacePatternSafeEnv, RegexOptions.Compiled)]
private static partial Regex GetReplacePatternSafeEnv();
#else
private static Regex GetReplacePatternSafeEnv() => new(ReplacePatternSafeEnv, RegexOptions.Compiled);
#endif
}