Skip to content

Instantly share code, notes, and snippets.

View 5cover's full-sized avatar

Scover 5cover

  • France
  • 03:09 (UTC +02:00)
View GitHub Profile
@5cover
5cover / functional_visitor_example.cs
Last active April 27, 2024 10:26
C# Visitor pattern compile-time safety example
// This visitor implementation attemps to make the best of both worlds, between C#'s functional features and compile-time safety.
// Using extension methods as visitors makes it a runtime error for there not to be an equivalent visitor for every subclass of the element hierarchy.
// This approach ensures compile-time safety, while minimizing boilerplate. It's a step closer to the ideal of "if it compiles, it works".
using System;
Room room = new Bathroom(10);
RoomVisitor visitorPrintSurface = new(
bathroom => Console.WriteLine($"Surface of bathroom: {bathroom.Surface}"),
@5cover
5cover / Extensions.cs
Created June 10, 2023 14:32
Check if path is in directory.
public static bool IsInDirectory(this FileInfo file, DirectoryInfo directory) => file.Directory?.IsInDirectory(directory) ?? false;
[SuppressMessage("Globalization", "CA1309", Justification = "Path comparison")]
public static bool IsInDirectory(this DirectoryInfo path, DirectoryInfo directory)
=> path.Parent != null && (path.Parent.FullName.Equals(directory.FullName, StringComparison.InvariantCultureIgnoreCase) || path.Parent.IsInDirectory(directory));
@5cover
5cover / TypeEventHandler.cs
Last active June 10, 2023 13:29
Type-safe event handler pattern. This pattern reduces the likelihood of an unhandled ``InvalidCastException`` since the ``sender`` argument of event handlers doesn't need to be casted. It also discourages the usage of closures to retrieve the sender with its original type.
/// <typeparam name="TSender">The type of the source of the event.</typeparam>
/// <typeparam name="TEventArgs">The type of event data generated by the event.</typeparam>
/// <remarks>Type-safe variation from <see cref="EventHandler{TEventArgs}"/>.</remarks>
/// <inheritdoc cref="EventHandler{TEventArgs}"/>
[Serializable]
[SuppressMessage("Naming", "CA1711", Justification = "Type-safe event handler pattern")]
public delegate void TypeEventHandler<TSender, TEventArgs>(TSender sender, TEventArgs e);
/// <typeparam name="TSender">The type of the source of the event.</typeparam>
/// <remarks>Type-safe variation from <see cref="EventHandler"/>.</remarks>
@5cover
5cover / Helpers.cs
Created June 9, 2023 18:03
Ensure admin privileges helper method. Restarts the application with admin privileges.
private static void EnsureAdminPrivileges()
{
if (new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator))
{
return;
}
ProcessStartInfo processInfo = new(Environment.ProcessPath.NotNull())
{
UseShellExecute = true,
Verb = "runas"
@5cover
5cover / Extensions.cs
Created June 6, 2023 21:02
C# Task WithTimeout() extension method
public static async Task WithTimeout(this Task task, TimeSpan timeout)
{
CancellationTokenSource cts = new();
if (task == await Task.WhenAny(task, Task.Delay(timeout, cts.Token)))
{
cts.Cancel();
}
else
{
throw new TimeoutException();
@5cover
5cover / Window.xaml
Created June 4, 2023 15:24
TextBlock bound to current size of window.
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0:F0}x{1:F0}">
<Binding ElementName="window" Path="ActualWidth" />
<Binding ElementName="window" Path="ActualHeight" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
@5cover
5cover / Extensions.cs
Created June 3, 2023 21:06
Erease selection of an ICollectionView
public static void EreaseSelection(this ICollectionView collectionView) => collectionView.MoveCurrentToPosition(-1);
@5cover
5cover / EqualsConverter.cs
Created June 1, 2023 18:44
Converter used to efficiently deal with radio buttons
using System.Globalization;
using System.Windows.Data;
/// <summary>A converter based on equality comparisons between the value and the parameter.</summary>
public sealed class EqualsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
=> Equals(value, parameter);
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
@5cover
5cover / Ref.cs
Created May 15, 2023 18:07
C# Reference wrapper
public sealed class Ref<T>
{
public Ref(T value) => Value = value;
public T Value { get; set; }
public static implicit operator T(Ref<T> @ref) => @ref.Value;
}
@5cover
5cover / Extensions.cs
Created May 1, 2023 16:57
FindVisualChildren C# WPF
public static IEnumerable<T> FindVisualChildren<T>(this DependencyObject depObj) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);
if (child is T t)
{
yield return t;
}
foreach (T childOfChild in FindVisualChildren<T>(child))