Pages

Thursday, February 15, 2018

Building VSJira extension [Part 7]: Read settings stored by the Options dialog into the VisualStudio extension

In the previous post of this series I wrote how to use a DialogPage to integrate settings into VisualStudio’s options dialog and use the settings store to persist settings for the extension. The next step is to make use of the settings from the extension itself. For example, when a user control is loaded, it needs to read which theme is selected from settings to apply the appropiate ResourceDictionaries. The control’s constructor looks like this:
public partial class JiraIssuesUserControl : UserControl
{
    private readonly JiraIssuesUserControlViewModel _viewModel;
    private readonly ThemeManager _themeManager;

    public JiraIssuesUserControl(JiraIssuesUserControlViewModel viewModel)
    {
        InitializeComponent();

        this.DataContext = this._viewModel = viewModel;

        var theme = viewModel.Services.VisualStudioServices.GetConfigurationOptions().Theme;
        _themeManager = new ThemeManager(this.Resources, theme);
    }
}
The user control receives its ViewModel as a dependency, as well as a reference to an instance of ‘VisualStudioServices’ that we can use to get the settings from the host. Here is the implementation:
public class VisualStudioServices : IVisualStudioServices
{
    private readonly DTE _env;

    public VisualStudioServices(DTE environment)
    {
        this._env = environment;
    }

    public IJiraOptions GetConfigurationOptions()
    {
        var result = new JiraOptions();
        var properties = this._env.get_Properties(JiraOptionsDialogPage.CategoryName, JiraOptionsDialogPage.PageName);

        if (properties != null)
        {
            result.MaxIssuesPerRequest = (int)properties.Item("MaxIssuesPerRequest").Value;   
        }

        return result;
    }
}
Notice here how the properties can be extracted directly from the DTE interface provided by VisualStudio. This is different than the JSON string that was used to serialize the settings to the SettingsStore that was shown on the previous post, VisualStudio first loads the settings from the store to hydrate the DialogPage object, but then has this API to access individual properties from the object. This is very strange design in my opinion, I felt like I had already wrote code to de-serialize settings into my own object, but now I have to write it again using a completely different API. Anyway, to close down this post, let’s see how the VisualStudio host create the instance of the VisualStudioServices class:
public sealed class VSJiraPackage : Microsoft.VisualStudio.Shell.Package
{
    public static VSJiraServices Services;

    protected override void Initialize()
    {
        DTE env = (DTE)GetService(typeof(DTE));

        Services = new VSJiraServices()
        {
            VisualStudioServices = new VisualStudioServices(env, this)
        };

        base.Initialize();
        
        ...
    }
}

The only relevant thing here is the GetService method to get an implementation of the DTE interface. VisualStudio has its own IOC container going on and this is the way to get a hold of all sort of services when the extension loads. In my case, I just keep a static instance of all the services that the extension can use and this is the object used whenever a WPF Window or UserControl is loaded into VisualStudio.

You can download the extension from the VisualStudio Marketplace or visit the project page to browse the source code.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.