This project has moved and is read-only. For the latest updates, please go here.

How to: Write a plugin for NuGet Package Explorer

Starting from version 1.5, you can write plugins for NuGet Package Explorer to display content of files inside a nuget package. By default, Package Explorer doesn’t know how to display every file extension. This is where plugins can fill in the gap.

A plugin can declare what file extensions it can show contents of. At runtime, when users trigger the View Content command on a file, Package Explorer searches for a plugin which can handle the file’s extension and calls it to display the content of the said file.

 

Following these steps to write a sample plugin:

1. Start by creating a C# class library project targeted at .NET framework 4.0 (either full or client profile). In 1.5, plugins classes have to be compiled into one single .dll file. Referencing other help assemblies is not supported (yet.)

2. Now using NuGet, install the NuGetPackageExplorer.Types package into your project.

extensionmanager

 

This package has a single assembly, NuGetPackageExplorer.Types.dll, which contains the contract types that plugins need to reference. The package also adds a class file named MyCustomContentViewer.cs to your project. This file contains the skeleton of a plugin class.

 

// TODO: replace '.extension' with your custom extension 
[PackageContentViewerMetadata(0, ".extension", ".anotherextension")] 
internal class MyCustomContentViewer : IPackageContentViewer 
{ 
    public object GetView(string extension, Stream stream) 
    { 
        throw new NotImplementedException(); 
    } 
} 

 

3. A plugin class is required to implement the IPackageContentViewer interface and be decorated with the PackageContentViewerMetadata attribute.

The constructor of the attribute accepts a priority value of integer type, and an array of extensions that this plugin can handle. The priority value is used when more than one plugins register for the same file extension. The plugin with lowest priority value is picked (priority of 0 is preferred over priority of 1). Notice that a plugin can register more than one file extensions.

The interface has a single method, GetView(), which is supposed to return the content view of the file. It is passed the extension of the file being viewed, and its content stream. Based on that, you are expected to return the WPF-friendly content of type ‘object’. This can be as simple as a string or any descendant type of the Visual class. At runtime, this object is assigned to a ContentPresenter control’s Content property.

Let’s say you want to create a viewer plugin for .pdb files. Here’s what it might look like:

 

[PackageContentViewerMetadata(0, ".pdb")] 
internal class PdbViewer : IPackageContentViewer 
{ 
     public object GetView(string extension, Stream stream) 
     { 
         return "This is the content of a .pdb file."; 
     } 
}

 

4. Now compile your project to get the assembly.

5. Next, you need to register your plugin with NuGet Package Explorer. Open Package Explorer, go to Tools menu and click on the Plugin Manager command. In the Plugin Manager dialog, click the Add button and select your plugin assembly. Note that you do NOT need to add the NuGetPackageExplorer.Types.dll assembly. That assembly is already loaded when Package Explorer runs. Click Close and you’re done.

pluginmanager

 

6. Now every time you choose to view content of a .pdb file, your plugin will be invoked to provide the content/view for it.

viewer

 

New in NuGet Package Explorer 2.0

In 2.0, there are two new extensibility points:

  • Custom package command - You can write a custom package command which will be displayed as a menu item under Tools. The command has access to an IPackage instance, which represents the currently opened package.
  • Custom package rule – You can write a custom rule which augments the set of default rules used by the Analyze Package command.

Important: In order to write plugins for NPE 2.0, you have to reference the version 2.0 of NuGetPackageExplorer.Types package. The version 1.0 only works with NPE 1.5 and 1.6.

 

1. Custom package command

To write a custom package command, create a class which implements the interface IPackageCommand and export it via the PackageCommandMetadataAttribute class. Here’s an example of how to do it:

    [PackageCommandMetadata("My custom command")]
    internal class MyCustomPackageCommand : IPackageCommand 
    {
        public void Execute(IPackage package) 
        {
            throw new NotImplementedException();
        }
    }

The string passed to the PackageCommandMetadata constructor is used as the menu label for the command under Tools menu. When user clicks on the menu command, your Execute method is invoked and passed an instance of IPackage that represents the current package.

 

2. Custom package rule

To write a custom package rule, create a class which implements the interface IPackageRule and export it using the normal MEF’s Export attribute.

    [Export(typeof(IPackageRule))]
    internal class MyCustomPackageRule : IPackageRule 
    {
        public IEnumerable<PackageIssue> Validate(IPackage package) 
        {
            throw new NotImplementedException();
        }
    }

When user clicks the Analyze Package command for the first time, all registered rules, including yours, are instantiated and the Validate() methods are called. From inside the method, again you have access to an instance of IPackage similar to the case of custom package command above.

Note that your custom rule class is created only once per session. This instance is shared among the invocations of Analyze Package commands. As a result, do not store states in your rule class.

Last edited Aug 30, 2011 at 7:10 PM by dotnetjunky, version 13