Skip to content

Commit

Permalink
dispose FileSystemWatcher in TP.Dispose() method
Browse files Browse the repository at this point in the history
  • Loading branch information
Vasily Kirichenko authored and Vasily Kirichenko committed Jun 11, 2014
1 parent e4c4f93 commit cff5b83
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 8 deletions.
3 changes: 2 additions & 1 deletion src/FsXaml.Wpf.TypeProvider/TypeProvider.Helper.fs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ let optionType ty = typedefof<option<_>>.MakeGenericType[| ty |]

/// Implements invalidation of schema when the file changes
let watchForChanges (ownerType:TypeProviderForNamespaces) (fileName:string) =
if fileName.StartsWith("http", System.StringComparison.InvariantCultureIgnoreCase) then () else
if fileName.StartsWith("http", System.StringComparison.InvariantCultureIgnoreCase) then None else

let path = Path.GetDirectoryName(fileName)
let name = Path.GetFileName(fileName)
let watcher = new FileSystemWatcher(Filter = name, Path = path)
watcher.Changed.Add(fun _ -> ownerType.Invalidate())
watcher.EnableRaisingEvents <- true
Some (watcher :> IDisposable)

// Get the assembly and namespace used to house the provided types
let thisAssembly = System.Reflection.Assembly.GetExecutingAssembly()
Expand Down
22 changes: 15 additions & 7 deletions src/FsXaml.Wpf.TypeProvider/XamlTypeProvider.fs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,13 @@ type public XamlTypeProvider(config : TypeProviderConfig) as this =
let assembly = Assembly.GetExecutingAssembly()
let nameSpace = this.GetType().Namespace
let providerType = ProvidedTypeDefinition(assembly, nameSpace, "XAML", Some typeof<obj>, IsErased = false)
let missingValue = "@@@missingValue###"
let fileSystemWatcher: IDisposable option ref = ref None

let disposeFileSystemWatcher() =
!fileSystemWatcher |> Option.iter (fun x ->
Diagnostics.Debug.WriteLine ("[FsXaml] Disposing FileSystemWatcher.")
x.Dispose())
fileSystemWatcher := None

let assemblies =
config.ReferencedAssemblies
Expand Down Expand Up @@ -260,21 +266,20 @@ type public XamlTypeProvider(config : TypeProviderConfig) as this =
instantiationFunction = (fun typeName parameterValues ->
let resourcePath = string parameterValues.[0]
let resolvedFileName = findConfigFile config.ResolutionFolder resourcePath
watchForChanges this resolvedFileName
disposeFileSystemWatcher()

This comment has been minimized.

Copy link
@dsyme

dsyme Jun 11, 2014

FWIW this logic isn't right - all watchers should be collected into a list of dispose actions, and all disposals done when the overall XamlTypeProvider object is disposed.

This comment has been minimized.

Copy link
@dsyme

dsyme Jun 11, 2014

This helps explain the number of watchers - there are mutliple lines like

type NewFolderNameDialog = FsXaml.XAML<"FolderNameDialog.xaml">

and one watcher is (correctly) created for each.

This comment has been minimized.

Copy link
@vasily-kirichenko

vasily-kirichenko Jun 11, 2014

Owner

Thanks! Fixed.

Diagnostics.Debug.WriteLine ("[FsXaml] Creating FileSystemWatcher.")
fileSystemWatcher := watchForChanges this resolvedFileName

use reader = new StreamReader(resolvedFileName)
let elements = XamlTypeUtils.readElements schemaContext reader resolvedFileName

let root = List.head elements

let ucType = typeof<System.Windows.Controls.UserControl>

let outerType =
let createFactoryType factoryType =
let outertype = ProvidedTypeDefinition(assembly, nameSpace, typeName, Some(factoryType), IsErased = false)
let ctor = ProvidedConstructor([])
ctor.BaseConstructorCall <- fun args -> factoryType.GetConstructors().[0], [Expr.Value(resourcePath)]
ctor.InvokeCode <- fun args -> <@@ 0 @@>
ctor.BaseConstructorCall <- fun _ -> factoryType.GetConstructors().[0], [Expr.Value(resourcePath)]
ctor.InvokeCode <- fun _ -> <@@ 0 @@>
outertype.AddMember ctor
outertype
match root.NodeType with
Expand All @@ -298,5 +303,8 @@ type public XamlTypeProvider(config : TypeProviderConfig) as this =

this.AddNamespace(nameSpace, [ providerType ])

interface IDisposable with
member __.Dispose() = disposeFileSystemWatcher()

[<assembly:TypeProviderAssembly>]
do()

0 comments on commit cff5b83

Please sign in to comment.