1+ using System ;
2+ using System . Diagnostics ;
3+ using System . IO ;
4+ using ServiceStack . Logging ;
5+
6+ namespace ServiceStack . Razor . Managers
7+ {
8+ public interface ILiveReload
9+ {
10+ void StartWatching ( string scanRootPath ) ;
11+ }
12+
13+ public class FileSystemWatcherLiveReload : ILiveReload
14+ {
15+ public static ILog Log = LogManager . GetLogger ( typeof ( FileSystemWatcherLiveReload ) ) ;
16+
17+ /// <summary>
18+ /// The purpose of the FileSystemWatcher is to ensure razor pages are
19+ /// consistent with the code generated by the razor engine. The file
20+ /// system watcher will invalidate pages and queue them for recompilation.
21+ /// </summary>
22+ protected FileSystemWatcher FileSystemWatcher ;
23+ private readonly ViewManager views ;
24+
25+ public FileSystemWatcherLiveReload ( ViewManager views )
26+ {
27+ this . views = views ;
28+ }
29+
30+ public void StartWatching ( string scanRootPath )
31+ {
32+ //setup the file system watcher for page invalidation
33+ this . FileSystemWatcher = new FileSystemWatcher ( scanRootPath , "*.*" )
34+ {
35+ IncludeSubdirectories = true ,
36+ EnableRaisingEvents = true ,
37+ //NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.FileName | NotifyFilters.LastWrite
38+ } ;
39+
40+ this . FileSystemWatcher . Changed += FileSystemWatcher_Changed ;
41+ this . FileSystemWatcher . Created += FileSystemWatcher_Created ;
42+ this . FileSystemWatcher . Deleted += FileSystemWatcher_Deleted ;
43+ this . FileSystemWatcher . Renamed += FileSystemWatcher_Renamed ;
44+ this . FileSystemWatcher . Error += FileSystemWatcher_Error ;
45+ }
46+
47+ /// <summary>
48+ /// Avoid throwing unhandled exception when shutting down ASP.NET host
49+ /// </summary>
50+ private void FileSystemWatcher_Error ( object sender , ErrorEventArgs e )
51+ {
52+ Log . WarnFormat ( "FileSystemWatcher Error: " , sender ) ;
53+ }
54+
55+ protected virtual void FileSystemWatcher_Renamed ( object sender , RenamedEventArgs e )
56+ {
57+ try
58+ {
59+ var oldPagePath = views . GetDictionaryPagePath ( views . GetRelativePath ( e . OldFullPath ) ) ;
60+
61+ if ( ! views . Pages . Remove ( oldPagePath ) )
62+ {
63+ Debugger . Break ( ) ;
64+ }
65+
66+ var newFile = views . GetVirutalFile ( e . FullPath ) ;
67+ if ( ! views . IsWatchedFile ( newFile ) ) return ;
68+
69+ views . TrackRazorPage ( newFile ) ;
70+ }
71+ catch ( Exception ex )
72+ {
73+ Log . Warn ( "FileSystemWatcher_Renamed error: " , ex ) ;
74+ }
75+ }
76+
77+ protected virtual void FileSystemWatcher_Deleted ( object sender , FileSystemEventArgs e )
78+ {
79+ try
80+ {
81+ var file = views . GetVirutalFile ( e . FullPath ) ;
82+ if ( ! views . IsWatchedFile ( file ) ) return ;
83+
84+ var pathPage = views . GetDictionaryPagePath ( file ) ;
85+
86+ views . Pages . Remove ( pathPage ) ;
87+ }
88+ catch ( Exception ex )
89+ {
90+ Log . Warn ( "FileSystemWatcher_Deleted error: " , ex ) ;
91+ }
92+ }
93+
94+ protected virtual void FileSystemWatcher_Created ( object sender , FileSystemEventArgs e )
95+ {
96+ try
97+ {
98+ var file = views . GetVirutalFile ( e . FullPath ) ;
99+ if ( ! views . IsWatchedFile ( file ) ) return ;
100+
101+ views . TrackRazorPage ( file ) ;
102+ }
103+ catch ( Exception ex )
104+ {
105+ Log . Warn ( "FileSystemWatcher_Created error: " , ex ) ;
106+ }
107+ }
108+
109+ protected virtual void FileSystemWatcher_Changed ( object sender , FileSystemEventArgs e )
110+ {
111+ try
112+ {
113+ var file = views . GetVirutalFile ( e . FullPath ) ;
114+ if ( ! views . IsWatchedFile ( file ) ) return ;
115+
116+ var pagePath = views . GetDictionaryPagePath ( file ) ;
117+
118+ RazorPage page ;
119+ if ( views . Pages . TryGetValue ( pagePath , out page ) && page . IsValid )
120+ {
121+ page . IsValid = false ;
122+ }
123+ }
124+ catch ( Exception ex )
125+ {
126+ Log . Warn ( "FileSystemWatcher_Changed error: " , ex ) ;
127+ }
128+ }
129+ }
130+ }
0 commit comments