Skip to content

Commit

Permalink
Utils WiP
Browse files Browse the repository at this point in the history
  • Loading branch information
scottt732 committed Nov 5, 2023
1 parent 3da1367 commit c88aea9
Show file tree
Hide file tree
Showing 19 changed files with 374 additions and 104 deletions.
10 changes: 7 additions & 3 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisLevel>latest</AnalysisLevel>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisLevel>latest</AnalysisLevel>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)Sholo.ruleset</CodeAnalysisRuleSet>
<NoWarn>1591,CA1848</NoWarn>
<NoWarn>1591,CA1848</NoWarn>
</PropertyGroup>

<PropertyGroup Label="Package">
Expand All @@ -35,9 +39,9 @@
</ItemGroup>

<ItemGroup Label="Package References">
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All" Version="2021.3.0" />
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" PrivateAssets="All" Version="16.8.55" />
<PackageReference Include="MinVer" PrivateAssets="All" Version="2.3.1" />
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All" Version="2023.2.0" />
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" PrivateAssets="All" Version="17.7.30" />
<PackageReference Include="MinVer" PrivateAssets="All" Version="4.3.0" />
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" Version="1.1.118" />
</ItemGroup>

Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<Target Name="Versioning" BeforeTargets="MinVer">
<PropertyGroup Label="Build">
<MinVerDefaultPreReleasePhase>preview</MinVerDefaultPreReleasePhase>
<MinVerDefaultPreReleaseIdentifiers>preview.0</MinVerDefaultPreReleaseIdentifiers>
<!-- Tag your repository with the semantic version e.g. '1.0.0' to version all NuGet packages. If you have
multiple NuGet packages in your solution and want to version them separately, then uncomment this line
and tag your repository with the name of the package followed by the semantic version e.g.
Expand Down
8 changes: 5 additions & 3 deletions Sholo.ruleset
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="General rules" Description="Style + Rules - Laziness" ToolsVersion="16.0">
<Rules AnalyzerId="Microsoft.CodeAnalysis.CSharp" RuleNamespace="Microsoft.CodeAnalysis.CSharp">
<Rule Id="CS1591" Action="None" />
Expand All @@ -13,7 +13,7 @@
<Rule Id="CA1812" Action="None" />
<Rule Id="CA1819" Action="None" />
<Rule Id="CA1822" Action="None" />
<Rule Id="CA2007" Action="Info" />
<Rule Id="CA2007" Action="None" />
</Rules>
<Rules AnalyzerId="Microsoft.NetCore.Analyzers" RuleNamespace="Microsoft.NetCore.Analyzers">
<Rule Id="CA1303" Action="None" />
Expand All @@ -26,9 +26,11 @@
<Rule Id="VSTHRD200" Action="Info" />
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<Rule Id="SA1000" Action="None" />
<Rule Id="SA1009" Action="None" />
<Rule Id="SA1101" Action="None" />
<Rule Id="SA1111" Action="None" />
<Rule Id="SA1118" Action="None" />
<Rule Id="SA1200" Action="None" />
<Rule Id="SA1201" Action="None" />
<Rule Id="SA1309" Action="None" />
Expand All @@ -43,4 +45,4 @@
<Rule Id="SA1629" Action="None" />
<Rule Id="SA1633" Action="None" />
</Rules>
</RuleSet>
</RuleSet>
2 changes: 1 addition & 1 deletion Source/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<Target Name="Versioning" BeforeTargets="MinVer">
<PropertyGroup Label="Build">
<MinVerDefaultPreReleasePhase>preview</MinVerDefaultPreReleasePhase>
<MinVerDefaultPreReleaseIdentifiers>preview.0</MinVerDefaultPreReleaseIdentifiers>
<!-- Tag your repository with the semantic version e.g. '1.0.0' to version all NuGet packages. If you have
multiple NuGet packages in your solution and want to version them separately, then uncomment this line
and tag your repository with the name of the package followed by the semantic version e.g.
Expand Down
56 changes: 28 additions & 28 deletions Source/Sholo.Utils/BaseServiceCollectionExtender.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
using System.Collections;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;

namespace Sholo.Utils
{
public abstract class BaseServiceCollectionExtender : IServiceCollection
{
public int Count => Target.Count;
public bool IsReadOnly => Target.IsReadOnly;
namespace Sholo.Utils;

public ServiceDescriptor this[int index]
{
get => Target[index];
set => Target[index] = value;
}
[PublicAPI]
public abstract class BaseServiceCollectionExtender : IServiceCollection
{
public int Count => Target.Count;
public bool IsReadOnly => Target.IsReadOnly;

protected IServiceCollection Target { get; }
public ServiceDescriptor this[int index]
{
get => Target[index];
set => Target[index] = value;
}

protected BaseServiceCollectionExtender(IServiceCollection target)
{
Target = target;
}
protected IServiceCollection Target { get; }

public IEnumerator<ServiceDescriptor> GetEnumerator() => Target.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => Target.GetEnumerator();
public void Add(ServiceDescriptor item) => Target.Add(item);
public void Clear() => Target.Clear();
public bool Contains(ServiceDescriptor item) => Target.Contains(item);
public void CopyTo(ServiceDescriptor[] array, int arrayIndex) => Target.CopyTo(array, arrayIndex);
public bool Remove(ServiceDescriptor item) => Target.Remove(item);
public int IndexOf(ServiceDescriptor item) => Target.IndexOf(item);
public void Insert(int index, ServiceDescriptor item) => Target.Insert(index, item);
public void RemoveAt(int index) => Target.RemoveAt(index);
protected BaseServiceCollectionExtender(IServiceCollection target)
{
Target = target;
}
}

public IEnumerator<ServiceDescriptor> GetEnumerator() => Target.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => Target.GetEnumerator();
public void Add(ServiceDescriptor item) => Target.Add(item);
public void Clear() => Target.Clear();
public bool Contains(ServiceDescriptor item) => Target.Contains(item);
public void CopyTo(ServiceDescriptor[] array, int arrayIndex) => Target.CopyTo(array, arrayIndex);
public bool Remove(ServiceDescriptor item) => Target.Remove(item);
public int IndexOf(ServiceDescriptor item) => Target.IndexOf(item);
public void Insert(int index, ServiceDescriptor item) => Target.Insert(index, item);
public void RemoveAt(int index) => Target.RemoveAt(index);
}
66 changes: 66 additions & 0 deletions Source/Sholo.Utils/Collections/LazyConcurrentDictionaryThing.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace Sholo.Utils.Collections;

[PublicAPI]
public class LazyConcurrentDictionaryThing<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
where TKey : notnull
{
private ConcurrentDictionary<TKey, Lazy<TValue>> Dictionary { get; } = new();

public TValue GetOrAdd(TKey key, Func<TValue> valueFactory) => Dictionary.GetOrAdd(key, _ => new Lazy<TValue>(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication)).Value;

public TValue this[TKey key] => Dictionary[key].Value;
public bool ContainsKey(TKey key) => Dictionary.ContainsKey(key);

public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => Dictionary.Select(x => new KeyValuePair<TKey, TValue>(x.Key, x.Value.Value)).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

public bool Remove(TKey key, out TValue value)
{
var result = Dictionary.Remove(key, out var val);

if (result)
{
value = val.Value;
return true;
}
else
{
value = default!;
return false;
}
}

public bool IsFixedSize => false;
public bool IsReadOnly => false;

public void Clear()
{
Dictionary.Clear();
}

public int Count => Dictionary.Count;

public bool TryGetValue(TKey key, out TValue value)
{
if (Dictionary.TryGetValue(key, out var lazyValue))
{
value = lazyValue.Value;
return true;
}
else
{
value = default;
return false;
}
}

public ICollection<TKey> Keys => Dictionary.Keys;
public ICollection<TValue> Values => Dictionary.Values.Select(x => x.Value).ToArray();
}
33 changes: 16 additions & 17 deletions Source/Sholo.Utils/EnumExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,23 @@
using System.ComponentModel;
using System.Linq;

namespace Sholo.Utils
namespace Sholo.Utils;

public static class EnumExtensions
{
public static class EnumExtensions
{
public static string GetDescription(this Enum value)
=> value.GetAttributeValue<DescriptionAttribute, string>(d => d.Description);
public static string GetDescription(this Enum value)
=> value.GetAttributeValue<DescriptionAttribute, string>(d => d.Description);

public static TAttribute GetAttribute<TAttribute>(this Enum value)
where TAttribute : Attribute
=> value.GetAttributeValue<TAttribute, TAttribute>(t => t);
public static TAttribute GetAttribute<TAttribute>(this Enum value)
where TAttribute : Attribute
=> value.GetAttributeValue<TAttribute, TAttribute>(t => t);

public static TValue GetAttributeValue<TAttribute, TValue>(this Enum value, Func<TAttribute, TValue> attributeValueSelector)
where TAttribute : Attribute
=> value.GetType()
.GetMember(value.ToString())
.SelectMany(x => x.GetCustomAttributes(typeof(TAttribute), false))
.Cast<TAttribute>()
.Select(attributeValueSelector)
.FirstOrDefault();
}
public static TValue GetAttributeValue<TAttribute, TValue>(this Enum value, Func<TAttribute, TValue> attributeValueSelector)
where TAttribute : Attribute
=> value.GetType()
.GetMember(value.ToString())
.SelectMany(x => x.GetCustomAttributes(typeof(TAttribute), false))
.Cast<TAttribute>()
.Select(attributeValueSelector)
.FirstOrDefault();
}
3 changes: 3 additions & 0 deletions Source/Sholo.Utils/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Global using directives

global using JetBrains.Annotations;
14 changes: 14 additions & 0 deletions Source/Sholo.Utils/IMeters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Diagnostics.Metrics;
using System.Runtime.CompilerServices;

namespace Sholo.Utils;

public interface IMeters
{
Meter Meter { get; }

TInstrument GetOrAddInstrument<TInstrument, T>(Func<Instrument<T>> valueFactory, [CallerMemberName] string name = null)
where TInstrument : Instrument<T>
where T : struct;
}
62 changes: 62 additions & 0 deletions Source/Sholo.Utils/Logging/LoggingBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Core;
using Serilog.Events;
using Serilog.Sinks.SystemConsole.Themes;

namespace Sholo.Utils.Logging;

public static class LoggingBuilderExtensions
{
public static ILoggingBuilder AddSerilogConsole(this ILoggingBuilder loggingBuilder, HostBuilderContext hostBuilderContext)
{
var configuration = hostBuilderContext.Configuration;
return AddSerilogConsole(loggingBuilder, configuration);
}

public static ILoggingBuilder AddSerilogConsole(this ILoggingBuilder loggingBuilder, IConfiguration configuration)
{
Logger logger;
var serilogKeys = configuration.GetSection("Serilog").AsEnumerable().ToArray();
if (serilogKeys.Any(x => x.Key != "Serilog"))
{
logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Filter.ByExcluding(DefaultFilters)
.CreateLogger();

loggingBuilder.AddSerilog(logger, true);
}
else
{
logger = new LoggerConfiguration()
.Filter.ByExcluding(DefaultFilters)
.WriteTo.Console(
LogEventLevel.Debug,
"[{Level:u3}] {Message:lj}{NewLine}{Exception}",
standardErrorFromLevel: LogEventLevel.Warning,
theme: AnsiConsoleTheme.Literate)
.CreateLogger();

loggingBuilder.AddSerilog(logger, true);
}

return loggingBuilder;
}

private static bool DefaultFilters(LogEvent le)
{
var sourceContext = le.Properties["SourceContext"]?.ToString() ?? string.Empty;

if (sourceContext.Contains("Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager", StringComparison.Ordinal) && le.Level < LogEventLevel.Warning)
{
return true;
}

return false;
}
}
26 changes: 26 additions & 0 deletions Source/Sholo.Utils/Meters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Diagnostics.Metrics;
using System.Runtime.CompilerServices;
using Sholo.Utils.Collections;

namespace Sholo.Utils;

[PublicAPI]
public class Meters : IMeters
{
public Meter Meter { get; }
private LazyConcurrentDictionaryThing<string, Instrument> Instruments { get; } = new();

public TInstrument GetOrAddInstrument<TInstrument, T>(Func<Instrument<T>> valueFactory, [CallerMemberName] string name = null)
where TInstrument : Instrument<T>
where T : struct
{
var result = Instruments.GetOrAdd(name, valueFactory);
return (TInstrument)result;
}

public Meters(string applicationName, [CanBeNull] string version)
{
Meter = new(applicationName, version);
}
}
Loading

0 comments on commit c88aea9

Please sign in to comment.