2011-10-19 27 views
13

से समाधान और प्रोजेक्ट इवेंट्स की सदस्यता कैसे ले सकता हूं मैं वीएसपीकेज के माध्यम से विजुअल स्टूडियो के लिए भाषा सेवा विकसित कर रहा हूं। जब भी समाधान की परियोजनाओं से फ़ाइलों को जोड़ा/निकाल दिया जाता है तो मुझे अपने पार्स डेटा को अपडेट करने की आवश्यकता होती है।मैं VSPackage

मैं समाधान और परियोजना की घटनाओं की सदस्यता लेना चाहता हूं।

मैंने निम्नानुसार प्रयास किया, लेकिन जब मैं समाधान में परियोजनाओं को जोड़ता/हटाता हूं या परियोजनाओं में वस्तुओं को जोड़ता/निकालता हूं तो इनमें से कोई भी घटना समाप्त नहीं होती है।

DTE dte = (DTE)languageService.GetService(typeof(DTE)); 
if (dte == null) 
    return; 

((Events2)dte.Events).SolutionEvents.ProjectAdded += SolutionEvents_ProjectAdded; 
((Events2)dte.Events).SolutionEvents.ProjectRemoved += SolutionEvents_ProjectRemoved; 
((Events2)dte.Events).ProjectItemsEvents.ItemAdded += ProjectItemsEvents_ItemAdded; 
((Events2)dte.Events).ProjectItemsEvents.ItemRemoved += ProjectItemsEvents_ItemRemoved; 

वीएसपीकेज से इन घटनाओं की सदस्यता लेने का सबसे अच्छा तरीका क्या है? किसी भी मदद की सराहना की!

उत्तर

8

डीटीई घटनाक्रम थोड़ा अजीब हैं, आपको घटना स्रोत ऑब्जेक्ट (समाधान मामले और प्रोजेक्टइटेम इवेंट्स को अपने मामले में कैश करने की आवश्यकता है), ताकि COM इंटरऑप उन्हें जीवित रखने के बारे में जानता हो। इस @ पर

public class MyClass 
{ 
    SolutionEvents solutionEvents; 

    public void ConnectToEvents() 
    { 
     solutionEvents = ((Events2)dte.Events).SolutionEvents; 
     solutionEvents.ProjectAdded += OnProjectAdded; 
     // Etc 
    } 
} 

अधिक http://msdn.microsoft.com/en-us/library/ms165650(v=vs.80).aspx

12

वैकल्पिक रूप से आप IVsSolutionEvents3 है, जो काफी बेहतर घटनाओं

[PackageRegistration(UseManagedResourcesOnly = true)] 
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] 
// add these 2 Annotations to execute Initialize() immediately when a project is loaded 
[ProvideAutoLoad(VSConstants.UICONTEXT.SolutionHasSingleProject_string)] 
[ProvideAutoLoad(VSConstants.UICONTEXT.SolutionHasMultipleProjects_string)] 
[Guid(GuidList.XYZ)] 
public sealed class UnityProjectUpdateHandlerPackage : Package, IVsSolutionEvents3 
{ 
    private DTE _dte; 
    private IVsSolution solution = null; 
    private uint _hSolutionEvents = uint.MaxValue; 

    protected override void Initialize() 
    { 
     Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString())); 
     base.Initialize(); 

     this._dte = (DTE) this.GetService(typeof(DTE)); 

     AdviseSolutionEvents(); 
    } 

    protected override void Dispose(bool disposing) 
    { 
     UnadviseSolutionEvents(); 

     base.Dispose(disposing); 
    } 

    private void AdviseSolutionEvents() 
    { 
     UnadviseSolutionEvents(); 

     solution = this.GetService(typeof(SVsSolution)) as IVsSolution; 

     if (solution != null) 
     { 
      solution.AdviseSolutionEvents(this, out _hSolutionEvents); 
     } 
    } 

    private void UnadviseSolutionEvents() 
    { 
     if (solution != null) 
     { 
      if (_hSolutionEvents != uint.MaxValue) 
      { 
       solution.UnadviseSolutionEvents(_hSolutionEvents); 
       _hSolutionEvents = uint.MaxValue; 
      } 

      solution = null; 
     } 
    } 

    private Project[] GetProjects() 
    { 
     return _dte.Solution.Projects 
      .Cast<Project>() 
      .Select(x => ((VSProject) x.Object).Project) 
      .ToArray(); 
    } 

    public int OnAfterLoadProject(IVsHierarchy pStubHierarchy, IVsHierarchy pRealHierarchy) 
    { 
     // Do something 
     return VSConstants.S_OK; 
    } 

    public int OnAfterOpenSolution(object pUnkReserved, int fNewSolution) 
    { 
     foreach (var project in GetProjects()) 
      ; // Do something 

     return VSConstants.S_OK; 
    } 

    public int OnBeforeUnloadProject(IVsHierarchy pRealHierarchy, IVsHierarchy pStubHierarchy) 
    { 
     // Do something 
     return VSConstants.S_OK; 
    } 

    public int OnAfterCloseSolution(object pUnkReserved) 
    { return VSConstants.S_OK; } 

    public int OnAfterClosingChildren(IVsHierarchy pHierarchy) 
    { return VSConstants.S_OK; } 

    public int OnAfterMergeSolution(object pUnkReserved) 
    { return VSConstants.S_OK; } 

    public int OnAfterOpenProject(IVsHierarchy pHierarchy, int fAdded) 
    { return VSConstants.S_OK; } 

    public int OnAfterOpeningChildren(IVsHierarchy pHierarchy) 
    { return VSConstants.S_OK; } 

    public int OnBeforeCloseProject(IVsHierarchy pHierarchy, int fRemoved) 
    { return VSConstants.S_OK; } 

    public int OnBeforeClosingChildren(IVsHierarchy pHierarchy) 
    { return VSConstants.S_OK; } 

    public int OnBeforeOpeningChildren(IVsHierarchy pHierarchy) 
    { return VSConstants.S_OK; } 

    public int OnBeforeCloseSolution(object pUnkReserved) 
    { return VSConstants.S_OK; } 

    public int OnQueryCloseProject(IVsHierarchy pHierarchy, int fRemoving, ref int pfCancel) 
    { return VSConstants.S_OK; } 

    public int OnQueryCloseSolution(object pUnkReserved, ref int pfCancel) 
    { return VSConstants.S_OK; } 

    public int OnQueryUnloadProject(IVsHierarchy pRealHierarchy, ref int pfCancel) 
    { return VSConstants.S_OK; } 
} 
+0

'प्रारंभ() 'में' _hSolutionEvents' क्या है? –

+0

आप सही हैं, कोड अपडेट किया गया है! 'UnhviseSolutionEvents' के लिए आवश्यक '_hSolutionEvents' पर एक और विचार था और नया कोड भी जोड़ें। यह एक शर्म की बात है कि सर्वश्रेष्ठ DevTool के लिए प्लगइन बनाने के बारे में बहुत अधिक जानकारी नहीं है ... – FooBarTheLittle

5

(ProjectAdded घटना पर ध्यान केंद्रित करने की सुविधा देता है, हालांकि वर्णित मुद्दा वास्तव में आराम के लिए एक ही है इस्तेमाल कर सकते हैं घटनाओं के)।

आपके द्वारा दिखाए गए कोड नमूने ProjectAdded ईवेंट के लिए SolutionEvents_ProjectAdded हैंडलर पंजीकृत करने का प्रयास करते हैं। हालांकि, घटना को उजागर करने वाली SolutionEvents ऑब्जेक्ट में, उसकी रैपिंग विधि को बंद करने के लिए सीमित जीवनकाल का दायरा है (आपने इसका हस्ताक्षर नहीं दिखाया है - चलो इसे Connect पर कॉल करें)। नियंत्रण प्रवाह करने के बाद कि गुंजाइश छोड़ दिया था, स्थानीय वस्तु पहले से ही, कचरा एकत्र किया जा सके इसके घटना कभी नहीं कहा जाता है:

टूटी कोड: SolutionEvents आवंटित करने के लिए

public class Connector 
{ 
    public void Connect() 
    { 
     ((Events2)dte.Events).SolutionEvents.ProjectAdded += SolutionEvents_ProjectAdded; 
    } 
    void SolutionEvents_ProjectAdded() 
    { 
     // callback is dead 
    } 
} 

कि ठीक करने के लिए, आप की जरूरत कुछ चर के लिए ऑब्जेक्ट, जिसका जीवनकाल SolutionEvents_ProjectAdded हैंडलर पर फैला है - उदाहरण के लिए पूरे लपेटने वर्ग पर। नीचे दिए गए उदाहरण में, गुंजाइश पूरे प्रकार (यह Connector कॉल) पर फैली है, और सुनिश्चित करता है कि हैंडलर उस प्रकार के जीवनकाल के दौरान पहुँचा जा सकता है:

फिक्स्ड कोड:

public class Connector 
{ 
    SolutionEvents _solutionEvents; 
    public void Connect() 
    { 
     _solutionEvents = ((Events2)dte.Events).SolutionEvents; 
     _solutionEvents.ProjectAdded += SolutionEvents_ProjectAdded; 
    } 
    void SolutionEvents_ProjectAdded() 
    { 
     // callback works 
    } 
} 

करने के लिए

प्रोग्रामिंग घटना संचालकों में एक आम गलती एक वस्तु है कि डब्ल्यू घोषित किया गया है करने के लिए घटना हैंडलर कनेक्ट कर रहा है: Scoping Variables Appropriately in Event Handlers - अधिक सटीक होना, इस MSDN संदर्भ जाँच घटना को संभालने के उद्देश्य से एक गुंजाइश सीमित है। ऑब्जेक्ट में जीवन होना चाहिए जो ऑब्जेक्ट के इवेंट हैंडलर के रूप में कॉलबैक विधि को कनेक्ट करने वाले फ़ंक्शन पर न केवल स्पैन करता है, बल्कि कॉलबैक विधि पर भी है जहां ईवेंट वास्तव में संभाला जाता है।अन्यथा, यदि ऑब्जेक्ट दायरे से बाहर है और अब कॉलबैक विधि में परिभाषित नहीं किया गया है, तो कॉलबैक विधि नहीं कहा जाता है और ईवेंट को वांछित के रूप में संभाला नहीं जाता है।