FileChangeManager.cs :  » Development » StyleCop » Microsoft » VisualStudio » Package » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Development » StyleCop 
StyleCop » Microsoft » VisualStudio » Package » FileChangeManager.cs
/***************************************************************************

Copyright (c) Microsoft Corporation. All rights reserved.
This code is licensed under the Visual Studio SDK license terms.
THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.

***************************************************************************/


namespace Microsoft.VisualStudio.Package{

  using System;
  using System.Collections.Generic;
  using System.Runtime.InteropServices;
  using System.Diagnostics;
  using System.Globalization;
  using Microsoft.VisualStudio.Shell.Interop;
  using Microsoft.VisualStudio.Shell;
  using IServiceProvider = System.IServiceProvider;

  /// <summary>
  /// This object is in charge of reloading nodes that have file monikers that can be listened to changes
  /// </summary>
  internal class FileChangeManager : IVsFileChangeEvents
  {
    #region nested objects
    /// <summary>
    /// Defines a data structure that can link a item moniker to the item and its file change cookie.
    /// </summary>
    private struct ObservedItemInfo
    {
      /// <summary>
      /// Defines the id of the item that is to be reloaded.
      /// </summary>
      private uint itemID;

      /// <summary>
      /// Defines the file change cookie that is returned when listening on file changes on the nested project item.
      /// </summary>
      private uint fileChangeCookie;

      /// <summary>
      /// Defines the nested project item that is to be reloaded.
      /// </summary>
      internal uint ItemID
      {
        get
        {
          return this.itemID;
        }

        set
        {
          this.itemID = value;
        }
      }

      /// <summary>
      /// Defines the file change cookie that is returned when listenning on file changes on the nested project item.
      /// </summary>
      internal uint FileChangeCookie
      {
        get
        {
          return this.fileChangeCookie;
        }

        set
        {
          this.fileChangeCookie = value;
        }
      }
    }
    #endregion

    #region Fields
    /// <summary>
    /// Event that is raised when one of the observed file names have changed on disk.
    /// </summary>
    internal event EventHandler<FileChangedOnDiskEventArgs> FileChangedOnDisk;

    /// <summary>
    /// Reference to the FileChange service.
    /// </summary>
    private IVsFileChangeEx fileChangeService;

    /// <summary>
    /// Maps between the observed item identified by its filename (in canonicalized form) and the cookie used for subscribing 
    /// to the events.
    /// </summary>
    private Dictionary<string, ObservedItemInfo> observedItems = new Dictionary<string, ObservedItemInfo>();

    /// <summary>
    /// Has Disposed already been called?
    /// </summary>
    private bool disposed;
    #endregion

    #region Constructor
    /// <summary>
    /// Overloaded ctor.
    /// </summary>
    /// <param name="nodeParam">An instance of a project item.</param>
    internal FileChangeManager(IServiceProvider serviceProvider)
    {
      #region input validation
      if (serviceProvider == null)
      {
        throw new ArgumentNullException("serviceProvider");
      }
      #endregion

      this.fileChangeService = (IVsFileChangeEx)serviceProvider.GetService(typeof(SVsFileChangeEx));

      if (this.fileChangeService == null)
      {
        // VS is in bad state, since the SVsFileChangeEx could not be proffered.
        throw new InvalidOperationException();
      }
    }
    #endregion

    #region IDisposable Members
    /// <summary>
    /// Disposes resources.
    /// </summary>
    public void Dispose()
    {
      // Don't dispose more than once
      if (this.disposed)
      {
        return;
      }

      this.disposed = true;

      // Unsubscribe from the observed source files.
      foreach (ObservedItemInfo info in this.observedItems.Values)
      {
        this.fileChangeService.UnadviseFileChange(info.FileChangeCookie);
      }

      // Clean the observerItems list
      this.observedItems.Clear();
    }
    #endregion

    #region IVsFileChangeEvents Members
    /// <summary>
    /// Called when one of the file have changed on disk.
    /// </summary>
    /// <param name="numberOfFilesChanged">Number of files changed.</param>
    /// <param name="filesChanged">Array of file names.</param>
    /// <param name="flags">Array of flags indicating the type of changes. See _VSFILECHANGEFLAGS.</param>
    /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code.</returns>
    int IVsFileChangeEvents.FilesChanged(uint numberOfFilesChanged, string[] filesChanged, uint[] flags)
    {
      if (this.FileChangedOnDisk != null)
      {
        for (int i = 0; i < numberOfFilesChanged; i++)
        {
          string fullFileName = Utilities.CanonicalizeFileName(filesChanged[i]);
          if (this.observedItems.ContainsKey(fullFileName))
          {
            ObservedItemInfo info = this.observedItems[fullFileName];
            this.FileChangedOnDisk(this, new FileChangedOnDiskEventArgs(fullFileName, info.ItemID, (_VSFILECHANGEFLAGS)flags[i]));
          }
        }
      }

      return VSConstants.S_OK;
    }

    /// <summary>
    /// Notifies clients of changes made to a directory. 
    /// </summary>
    /// <param name="directory">Name of the directory that had a change.</param>
    /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code. </returns>
    int IVsFileChangeEvents.DirectoryChanged(string directory)
    {
      return VSConstants.S_OK;
    }
    #endregion

    #region helpers  
    /// <summary>
    /// Observe when the given file is updated on disk. In this case we do not care about the item id that represents the file in the hierarchy.
    /// </summary>
    /// <param name="fileName">File to observe.</param>
    internal void ObserveItem(string fileName)
    {
      this.ObserveItem(fileName, VSConstants.VSITEMID_NIL);
    }
    
    /// <summary>
    /// Observe when the given file is updated on disk.
    /// </summary>
    /// <param name="fileName">File to observe.</param>
    /// <param name="id">The item id of the item to observe.</param>
    internal void ObserveItem(string fileName, uint id)
    {
      #region Input validation
      if (String.IsNullOrEmpty(fileName))
      {
        throw new ArgumentException(SR.GetString(SR.InvalidParameter, CultureInfo.CurrentUICulture), "fileName");
      }
      #endregion

      string fullFileName = Utilities.CanonicalizeFileName(fileName);
      if (!this.observedItems.ContainsKey(fullFileName))
      {
        // Observe changes to the file
        uint fileChangeCookie;
        ErrorHandler.ThrowOnFailure(this.fileChangeService.AdviseFileChange(fullFileName, (uint)(_VSFILECHANGEFLAGS.VSFILECHG_Time | _VSFILECHANGEFLAGS.VSFILECHG_Del), this, out fileChangeCookie));

        ObservedItemInfo itemInfo = new ObservedItemInfo();
        itemInfo.ItemID = id;
        itemInfo.FileChangeCookie = fileChangeCookie;

        // Remember that we're observing this file (used in FilesChanged event handler)
        this.observedItems.Add(fullFileName, itemInfo);
      }
    }

    /// <summary>
    /// Ignore item file changes for the specified item.
    /// </summary>
    /// <param name="fileName">File to ignore observing.</param>
    /// <param name="ignore">Flag indicating whether or not to ignore changes (1 to ignore, 0 to stop ignoring).</param>
    internal void IgnoreItemChanges(string fileName, bool ignore)
    {
      #region Input validation
      if (String.IsNullOrEmpty(fileName))
      {
        throw new ArgumentException(SR.GetString(SR.InvalidParameter, CultureInfo.CurrentUICulture), "fileName");
      }
      #endregion

      string fullFileName = Utilities.CanonicalizeFileName(fileName);
      if (this.observedItems.ContainsKey(fullFileName))
      {
        // Call ignore file with the flags specified.
        ErrorHandler.ThrowOnFailure(this.fileChangeService.IgnoreFile(0, fileName, ignore ? 1 : 0));
      }
    }

    /// <summary>
    /// Stop observing when the file is updated on disk.
    /// </summary>
    /// <param name="fileName">File to stop observing.</param>
    internal void StopObservingItem(string fileName)
    {
      #region Input validation
      if (String.IsNullOrEmpty(fileName))
      {
        throw new ArgumentException(SR.GetString(SR.InvalidParameter, CultureInfo.CurrentUICulture), "fileName");
      }
      #endregion

      string fullFileName = Utilities.CanonicalizeFileName(fileName);

      if (this.observedItems.ContainsKey(fullFileName))
      {
        // Get the cookie that was used for this.observedItems to this file.
        ObservedItemInfo itemInfo = this.observedItems[fullFileName];

        // Remove the file from our observed list. It's important that this is done before the call to 
        // UnadviseFileChange, because for some reason, the call to UnadviseFileChange can trigger a 
        // FilesChanged event, and we want to be able to filter that event away.
        this.observedItems.Remove(fullFileName);

        // Stop observing the file
        ErrorHandler.ThrowOnFailure(this.fileChangeService.UnadviseFileChange(itemInfo.FileChangeCookie));
      }
    }
    #endregion
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.