Skip to content

Instantly share code, notes, and snippets.

View egil's full-sized avatar

Egil Hansen egil

View GitHub Profile
@egil
egil / RecordList.cs
Last active March 22, 2024 11:37
RecordList - a List<T> that supports deep equality and hashing that include items in the list. The equality is does not take order of items into consideration. Useful in combination with C# record types.
public sealed class RecordList<T> : List<T>, IEquatable<RecordList<T>>
where T : IEquatable<T>
{
private static readonly int EmptyRecordListHashCode = typeof(RecordList<T>).FullName!.GetHashCode(StringComparison.Ordinal);
public RecordList()
{
}
public RecordList(IEnumerable<T> collection)
@egil
egil / CustomerRepository.cs
Last active April 1, 2024 14:11
A helper class DatabaseMemoryCache that uses Microsoft.Extensions.Caching.Memory.IMemoryCaching to cache async tasks their result data, e.g. EF core queries. The CustomerRepository below shows an example of how to use it.
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
namespace Solution.Data;
public sealed class CustomerRepository : IDisposable
{
private readonly IDbContextFactory<DbContext> dbFactory;
private readonly DatabaseMemoryCache databaseCache;
@egil
egil / appServiceWithSiteExtension.bicep
Created September 25, 2023 16:13
An example of using bicep to create a Azure App Service running Windows and .NET 8 preview
param resourceName string
param subnetId string
param appServicePlanId string
param appsettingsProperties object
param location string = resourceGroup().location
param tags object = resourceGroup().tags
param eventHubNames array
resource appService 'Microsoft.Web/sites@2022-09-01' = {
name: resourceName
@egil
egil / embed-changelog-in-library.csproj
Created September 5, 2023 13:45
Want to embed a changelog file's content inside the <PackageReleaseNotes> in your libraries, so it is readily visible on NuGET, you can do the following:
<!--
Automatically copy the content of a CHANGELOG.md file into a NuGET package's change log section via the `<PackageReleaseNotes>` element in .csproj by doing the following:
Put the following into your .csproj, e.g. `Lib.csproj`, and the content of your CHANGELOG.md will be embedded when the project is packaged.
This assumes that the project structure is as follows:
\CHANGELOG.md
\src\Lib\Lib.csproj
-->
@egil
egil / Invoke-With-Retry.ps1
Created March 20, 2023 12:04
A PowerShell helper function that will invoke a script block a number of times until it completes successfully, with a configurable delay between retries.
function Invoke-With-Retry {
[CmdletBinding()]
Param(
[Parameter(Position = 0, Mandatory = $true)]
[scriptblock]$ScriptBlock,
[Parameter(Position = 1, Mandatory = $false)]
[int]$Retries = 5,
[Parameter(Position = 2, Mandatory = $false)]
@egil
egil / OptionsExtensions.cs
Last active January 12, 2023 15:22
Helper methods for reading values from options types at runtime
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace Microsoft.Extensions.Options;
public static class OptionsExtensions
{
@egil
egil / ITimeScheduler.cs
Last active January 16, 2023 11:32
Time scheduler for production and testing (completely untested code at this point)
namespace Scheduler;
public interface ITimeScheduler
{
DateTimeOffset UtcNow { get; }
Task Delay(TimeSpan delay);
Task Delay(TimeSpan delay, CancellationToken cancellationToken);
@egil
egil / MulticastAsyncEnumerable.cs
Last active June 25, 2023 10:45
A multi-cast IAsyncEnumerable<T>, where each reader/subscriber/iterator gets their own copy of the items passed to the enumerable, and can process them asynchronously at their own pace. Since it implements `IAsyncEnumerable<T>`, users can use all the LINQ style operators available in the System.Linq.Async package for easy filtering, projecting, …
/// <summary>
/// Represents a multi-cast <see cref="IAsyncEnumerable{T}"/> where
/// each reader can consume the <typeparamref name="T"/> items
/// at its own pace.
/// </summary>
/// <typeparam name="T">The item type produced by the enumerable.</typeparam>
public sealed class MulticastAsyncEnumerable<T> : IAsyncEnumerable<T>
{
private readonly UnboundedChannelOptions channelOptions;
private readonly object activeChannelsLock = new object();
@egil
egil / StringAssertionExtensions.cs
Last active May 4, 2021 15:07
C# source code comparison / assertion helper (depends on the packages Microsoft.CodeAnalysis.CSharp and DiffPlex).
using System;
using System.Text;
using DiffPlex.DiffBuilder;
using DiffPlex.DiffBuilder.Model;
using FluentAssertions.Execution;
using FluentAssertions.Primitives;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
namespace FluentAssertions
@egil
egil / IdFactory.cs
Last active January 17, 2021 17:17
This can be used to hash key/value pairs, that should be used as a ID in e.g. a database like CosmosDB. This will produce the same length key, no matter how many key/value pairs are supplied.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
public static class IdFactory
{
public static string CreateId(IEnumerable<(string key, string value)> kvps)