|
7 | 7 | */ |
8 | 8 |
|
9 | 9 | // ReSharper disable UnusedMember.Global |
10 | | - |
11 | 10 | using System; |
12 | 11 | using System.IO; |
| 12 | +using System.Threading; |
13 | 13 | using System.Threading.Tasks; |
14 | 14 |
|
15 | 15 | namespace FileHandler; |
16 | 16 |
|
17 | | -public class FileObserver |
| 17 | +/// <summary> |
| 18 | +/// Observes a folder for changes and raises async events. |
| 19 | +/// Supports cancellation via <see cref="CancellationToken"/>. |
| 20 | +/// </summary> |
| 21 | +public class FileObserver : IDisposable |
18 | 22 | { |
| 23 | + private readonly FileSystemWatcher _watcher; |
| 24 | + |
19 | 25 | /// <summary> |
20 | | - /// Searches the folder asynchronous. |
| 26 | + /// Triggered when a file or folder is created. |
21 | 27 | /// </summary> |
22 | | - /// <param name="path">The path.</param> |
23 | | - public async Task SearchFolderAsync(string path) |
24 | | - { |
25 | | - var watcher = new FileSystemWatcher(path) |
26 | | - { |
27 | | - NotifyFilter = NotifyFilters.DirectoryName | NotifyFilters.FileName, |
28 | | - IncludeSubdirectories = true, |
29 | | - InternalBufferSize = 64 * 1024 // Increase buffer size to handle more events |
30 | | - }; |
| 28 | + public event Func<FileSystemEventArgs, Task>? Created; |
31 | 29 |
|
32 | | - watcher.Created += OnCreated; |
33 | | - watcher.Changed += OnChanged; |
34 | | - watcher.Deleted += OnDeleted; |
35 | | - watcher.Error += OnError; |
| 30 | + /// <summary> |
| 31 | + /// Triggered when a file or folder is changed. |
| 32 | + /// </summary> |
| 33 | + public event Func<FileSystemEventArgs, Task>? Changed; |
36 | 34 |
|
37 | | - watcher.EnableRaisingEvents = true; |
| 35 | + /// <summary> |
| 36 | + /// Triggered when a file or folder is deleted. |
| 37 | + /// </summary> |
| 38 | + public event Func<FileSystemEventArgs, Task>? Deleted; |
38 | 39 |
|
39 | | - Console.WriteLine("Monitoring folder for changes. Press any key to stop."); |
40 | | - await Task.Run(Console.ReadKey); // Run in background to avoid blocking |
| 40 | + /// <summary> |
| 41 | + /// Triggered when a file or folder is renamed. |
| 42 | + /// </summary> |
| 43 | + public event Func<RenamedEventArgs, Task>? Renamed; |
41 | 44 |
|
42 | | - watcher.EnableRaisingEvents = false; |
43 | | - watcher.Dispose(); |
44 | | - } |
| 45 | + /// <summary> |
| 46 | + /// Triggered on watcher errors. |
| 47 | + /// </summary> |
| 48 | + public event Func<ErrorEventArgs, Task>? Error; |
45 | 49 |
|
46 | 50 | /// <summary> |
47 | | - /// Called when [created]. |
| 51 | + /// Initializes a new instance of <see cref="FileObserver"/>. |
48 | 52 | /// </summary> |
49 | | - /// <param name="sender">The sender.</param> |
50 | | - /// <param name="e">The <see cref="FileSystemEventArgs" /> instance containing the event data.</param> |
51 | | - private static void OnCreated(object sender, FileSystemEventArgs e) |
| 53 | + /// <param name="path">Folder to observe.</param> |
| 54 | + public FileObserver(string path) |
52 | 55 | { |
53 | | - Console.WriteLine($"File or folder '{e.FullPath}' was created."); |
| 56 | + if (!Directory.Exists(path)) |
| 57 | + throw new DirectoryNotFoundException(path); |
| 58 | + |
| 59 | + _watcher = new FileSystemWatcher(path) |
| 60 | + { |
| 61 | + NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.LastWrite, |
| 62 | + IncludeSubdirectories = true, |
| 63 | + InternalBufferSize = 64 * 1024 |
| 64 | + }; |
| 65 | + |
| 66 | + _watcher.Created += async (s, e) => { if (Created != null) await Created.Invoke(e); }; |
| 67 | + _watcher.Changed += async (s, e) => { if (Changed != null) await Changed.Invoke(e); }; |
| 68 | + _watcher.Deleted += async (s, e) => { if (Deleted != null) await Deleted.Invoke(e); }; |
| 69 | + _watcher.Renamed += async (s, e) => { if (Renamed != null) await Renamed.Invoke(e); }; |
| 70 | + _watcher.Error += async (s, e) => { if (Error != null) await Error.Invoke(e); }; |
54 | 71 | } |
55 | 72 |
|
56 | 73 | /// <summary> |
57 | | - /// Called when [changed]. |
| 74 | + /// Starts watching the folder. |
58 | 75 | /// </summary> |
59 | | - /// <param name="sender">The sender.</param> |
60 | | - /// <param name="e">The <see cref="FileSystemEventArgs" /> instance containing the event data.</param> |
61 | | - private static void OnChanged(object sender, FileSystemEventArgs e) |
62 | | - { |
63 | | - Console.WriteLine($"File or folder '{e.FullPath}' was modified."); |
64 | | - } |
| 76 | + public void Start() => _watcher.EnableRaisingEvents = true; |
65 | 77 |
|
66 | 78 | /// <summary> |
67 | | - /// Called when [deleted]. |
| 79 | + /// Stops watching the folder. |
68 | 80 | /// </summary> |
69 | | - /// <param name="sender">The sender.</param> |
70 | | - /// <param name="e">The <see cref="FileSystemEventArgs" /> instance containing the event data.</param> |
71 | | - private static void OnDeleted(object sender, FileSystemEventArgs e) |
72 | | - { |
73 | | - Console.WriteLine($"File or folder '{e.FullPath}' was deleted."); |
74 | | - } |
| 81 | + public void Stop() => _watcher.EnableRaisingEvents = false; |
75 | 82 |
|
76 | 83 | /// <summary> |
77 | | - /// Called when [error]. |
| 84 | + /// Runs the observer until cancelled via token. |
78 | 85 | /// </summary> |
79 | | - /// <param name="sender">The sender.</param> |
80 | | - /// <param name="e">The <see cref="ErrorEventArgs" /> instance containing the event data.</param> |
81 | | - private static void OnError(object sender, ErrorEventArgs e) |
| 86 | + /// <param name="cancellationToken">Token to stop watching.</param> |
| 87 | + /// <returns>Task that completes when cancelled.</returns> |
| 88 | + public Task RunUntilCancelledAsync(CancellationToken cancellationToken) |
82 | 89 | { |
83 | | - Console.WriteLine("Error occurred: " + e.GetException().Message); |
| 90 | + Start(); |
| 91 | + var tcs = new TaskCompletionSource<object?>(); |
| 92 | + cancellationToken.Register(() => |
| 93 | + { |
| 94 | + Stop(); |
| 95 | + tcs.TrySetResult(null); |
| 96 | + }); |
| 97 | + return tcs.Task; |
84 | 98 | } |
| 99 | + |
| 100 | + /// <summary> |
| 101 | + /// Disposes the internal watcher. |
| 102 | + /// </summary> |
| 103 | + public void Dispose() => _watcher.Dispose(); |
85 | 104 | } |
| 105 | + |
| 106 | + |
0 commit comments