Added DirectoryObserver

This commit is contained in:
TheXamlGuy
2024-09-29 13:10:39 +01:00
parent dc1afd5750
commit 760ce933bd
5 changed files with 96 additions and 49 deletions
+54
View File
@@ -0,0 +1,54 @@
using System.Collections.Concurrent;
namespace Toolkit.Foundation;
public class DirectoryObserver
{
public static async Task<string[]> EnumerateFiles(string path,
string[] filter,
int count,
CancellationToken cancellationToken = default)
{
string[] files = [];
HashSet<string> extensions = filter.Select(x => $".{x.ToLower()}").ToHashSet();
bool IsBatchComplete()
{
files = Directory.EnumerateFiles(path, "*.*", SearchOption.TopDirectoryOnly)
.Where(x => extensions.Contains(Path.GetExtension(x).ToLower()))
.ToArray();
if (files.Length != count)
{
return false;
}
ConcurrentBag<bool> fileAccessResults = [];
Parallel.ForEach(files, (file) =>
{
try
{
using FileStream fileStream = new(file, FileMode.Open, FileAccess.Read, FileShare.None);
fileAccessResults.Add(true);
}
catch (IOException)
{
fileAccessResults.Add(false);
}
});
return fileAccessResults.All(result => result);
}
await Task.Run(async () =>
{
while (!IsBatchComplete())
{
cancellationToken.ThrowIfCancellationRequested();
await Task.Delay(5000, cancellationToken);
}
}, cancellationToken);
return files;
}
}
+2 -2
View File
@@ -12,12 +12,12 @@ public interface IMediator
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
where TMessage : notnull; where TMessage : notnull;
IAsyncEnumerable<object?> HandleManyAsync(Type responseType, IAsyncEnumerable<object?> HandleAsyncMany(Type responseType,
object message, object message,
object? key = null, object? key = null,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
IAsyncEnumerable<TResponse?> HandleManyAsync<TMessage, TResponse>(TMessage message, IAsyncEnumerable<TResponse?> HandleAsyncMany<TMessage, TResponse>(TMessage message,
object? key = null, object? key = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
where TMessage : notnull; where TMessage : notnull;
+36 -34
View File
@@ -23,7 +23,7 @@ public class Mediator(IHandlerProvider handlerProvider,
MethodInfo? handleMethod = handler?.GetType().GetMethod("Handle", [message.GetType(), typeof(CancellationToken)]); MethodInfo? handleMethod = handler?.GetType().GetMethod("Handle", [message.GetType(), typeof(CancellationToken)]);
if (handleMethod is not null) if (handleMethod is not null)
{ {
return await (Task<TResponse?>)handleMethod.Invoke(handler, new object[] { message, cancellationToken })!; return await (Task<TResponse?>)handleMethod.Invoke(handler, [message, cancellationToken])!;
} }
} }
@@ -47,7 +47,7 @@ public class Mediator(IHandlerProvider handlerProvider,
if (handleMethod is not null) if (handleMethod is not null)
{ {
dynamic task = handleMethod.Invoke(handler, new object[] { message, cancellationToken })!; dynamic task = handleMethod.Invoke(handler, [message, cancellationToken])!;
await task; await task;
return task.Result; return task.Result;
@@ -57,35 +57,7 @@ public class Mediator(IHandlerProvider handlerProvider,
return default; return default;
} }
public async Task<List<object?>> HandleMany(Type responseType, public async IAsyncEnumerable<object?> HandleAsyncMany(Type responseType,
object message,
object? key = null,
CancellationToken cancellationToken = default)
{
List<object?> responses = [];
await foreach (object? response in HandleManyAsync(responseType, message, key, cancellationToken))
{
responses.Add(response);
}
return responses;
}
public async Task<IList<TResponse?>> HandleMany<TMessage, TResponse>(TMessage message,
object? key = null,
CancellationToken cancellationToken = default)
where TMessage : notnull
{
List<TResponse?> responses = [];
await foreach (TResponse? response in HandleManyAsync<TMessage, TResponse>(message, key, cancellationToken))
{
responses.Add(response);
}
return responses;
}
public async IAsyncEnumerable<object?> HandleManyAsync(Type responseType,
object message, object message,
object? key = null, object? key = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default) [EnumeratorCancellation] CancellationToken cancellationToken = default)
@@ -102,12 +74,12 @@ public class Mediator(IHandlerProvider handlerProvider,
if (handleMethod is not null) if (handleMethod is not null)
{ {
yield return await (Task<object?>)handleMethod.Invoke(handler, new object[] { message, cancellationToken })!; yield return await (Task<object?>)handleMethod.Invoke(handler, [message, cancellationToken])!;
} }
} }
} }
public async IAsyncEnumerable<TResponse?> HandleManyAsync<TMessage, TResponse>(TMessage message, public async IAsyncEnumerable<TResponse?> HandleAsyncMany<TMessage, TResponse>(TMessage message,
object? key = null, object? key = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default) [EnumeratorCancellation] CancellationToken cancellationToken = default)
where TMessage : notnull where TMessage : notnull
@@ -122,11 +94,38 @@ public class Mediator(IHandlerProvider handlerProvider,
MethodInfo? handleMethod = handler?.GetType().GetMethod("Handle", [message.GetType(), typeof(CancellationToken)]); MethodInfo? handleMethod = handler?.GetType().GetMethod("Handle", [message.GetType(), typeof(CancellationToken)]);
if (handleMethod is not null) if (handleMethod is not null)
{ {
yield return await (Task<TResponse?>)handleMethod.Invoke(handler, new object[] { message, cancellationToken })!; yield return await (Task<TResponse?>)handleMethod.Invoke(handler, [message, cancellationToken])!;
} }
} }
} }
public async Task<List<object?>> HandleMany(Type responseType,
object message,
object? key = null,
CancellationToken cancellationToken = default)
{
List<object?> responses = [];
await foreach (object? response in HandleAsyncMany(responseType, message, key, cancellationToken))
{
responses.Add(response);
}
return responses;
}
public async Task<IList<TResponse?>> HandleMany<TMessage, TResponse>(TMessage message,
object? key = null,
CancellationToken cancellationToken = default)
where TMessage : notnull
{
List<TResponse?> responses = [];
await foreach (TResponse? response in HandleAsyncMany<TMessage, TResponse>(message, key, cancellationToken))
{
responses.Add(response);
}
return responses;
}
private List<object?> GetHandlers(object message, private List<object?> GetHandlers(object message,
Type handlerWrapperType, Type handlerWrapperType,
object? key) object? key)
@@ -155,8 +154,11 @@ public class Mediator(IHandlerProvider handlerProvider,
provider.GetServices(handlerWrapperType); provider.GetServices(handlerWrapperType);
AddHandlers(keyedServices); AddHandlers(keyedServices);
if (key is not null)
{
IEnumerable<object?> additionalHandlers = handlerProvider.Get(key); IEnumerable<object?> additionalHandlers = handlerProvider.Get(key);
AddHandlers(additionalHandlers); AddHandlers(additionalHandlers);
}
return handlers.SelectMany(entry => entry.Value).ToList(); return handlers.SelectMany(entry => entry.Value).ToList();
} }
-5
View File
@@ -1,5 +0,0 @@
namespace Toolkit.Foundation;
public static class MediatorExtensions
{
}
@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:CompileBindings="True"> x:CompileBindings="True">
<ControlTheme x:Key="{x:Type TabStrip}" TargetType="TabStrip"> <ControlTheme x:Key="{x:Type TabStrip}" TargetType="TabStrip">
<Setter Property="MinHeight" Value="32" /> <Setter Property="MinHeight" Value="36" />
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" /> <Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
<Setter Property="Background" Value="{DynamicResource ControlAltFillColorSecondaryBrush}" /> <Setter Property="Background" Value="{DynamicResource ControlAltFillColorSecondaryBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource ControlStrokeColorDefaultBrush}" /> <Setter Property="BorderBrush" Value="{DynamicResource ControlStrokeColorDefaultBrush}" />
@@ -45,7 +45,7 @@
<Setter Property="BorderBrush" Value="{DynamicResource ControlFillColorTransparentBrush}" /> <Setter Property="BorderBrush" Value="{DynamicResource ControlFillColorTransparentBrush}" />
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" /> <Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" />
<Setter Property="FontWeight" Value="Normal" /> <Setter Property="FontWeight" Value="Normal" />
<Setter Property="Height" Value="32" /> <Setter Property="MinHeight" Value="36" />
<Setter Property="MinWidth" Value="60" /> <Setter Property="MinWidth" Value="60" />
<Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}" /> <Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}" />
<Setter Property="VerticalAlignment" Value="Stretch" /> <Setter Property="VerticalAlignment" Value="Stretch" />
@@ -66,7 +66,6 @@
<BrushTransition Property="Background" Duration="00:00:00.083" /> <BrushTransition Property="Background" Duration="00:00:00.083" />
</Transitions> </Transitions>
</Border.Transitions> </Border.Transitions>
<Panel> <Panel>
<Border <Border
Name="Hover" Name="Hover"
@@ -83,7 +82,6 @@
</Transitions> </Transitions>
</Border.Transitions> </Border.Transitions>
</Border> </Border>
<ContentPresenter <ContentPresenter
Name="PART_ContentPresenter" Name="PART_ContentPresenter"
Margin="11,5,11,6" Margin="11,5,11,6"
@@ -95,7 +93,6 @@
ContentTemplate="{TemplateBinding ContentTemplate}" ContentTemplate="{TemplateBinding ContentTemplate}"
FontWeight="{TemplateBinding FontWeight}" FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}" /> Foreground="{TemplateBinding Foreground}" />
<Rectangle <Rectangle
Name="Pill" Name="Pill"
Width="4" Width="4"
@@ -122,7 +119,6 @@
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>
<Style Selector="^:pointerover"> <Style Selector="^:pointerover">
<Style Selector="^ /template/ Border#Hover"> <Style Selector="^ /template/ Border#Hover">
<Setter Property="Background" Value="{DynamicResource SubtleFillColorSecondaryBrush}" /> <Setter Property="Background" Value="{DynamicResource SubtleFillColorSecondaryBrush}" />