Creating a Comicster Extension

Comicster uses NuGet and MEF to allow for third-party plug-ins. In this article, we'll be describing the various extensibility points in Comicster and how you can write your own plug-ins.

You should be familiar with Microsoft .NET Framework and Microsoft Visual Studio. Comicster extensions can be written in any .NET language (C#, VB.NET, etc.). The below examples will be shown using Visual C#. Extensions can be written using the free Visual Studio Express editions. In fact, Comicster was written using the Visual Studio C# Express.

To learn how to create a Comicster Skin extension, please refer to the "How do I create a skin?" knowledge base article.

Development Overview

The below 10 step process overview provides you with a quick and simple understanding of how to code, build, test, and submit your Comicster Plug-In.

Design and Development Phase

  1. Create a new "Class Library" project in Visual Studio and add a reference to Comicster.Core.DLL
  2. Code your plug-in by implementing the provided interface(s)
  3. Build your library
  4. Package your library and any dependencies into a nupkg file

Testing Phase

  1. Copy your nupkg file into your local package directory at "My Documents\Comicster\Packages"
  2. If you haven't bumped the nupkg version, delete any previously installed versions of your plug-in from the installed extensions directory at "My Documents\Comicster\Extensions"
  3. Start Comicster
  4. Click "Tools|Extensions" menu choice and install your plug-in
  5. Thoroughly test your plug-in's functionality

Submission Phase

  1. Submit the nupkg file to Comicster.net

Writing and Naming Your Plug-In

By convention, all "first party" extensions (official Comicster extensions) will be named Comicster.Type.Name.dll. For example, "Comicster.Tools.CmxMerger", "Comicster.IO.Cmx" or "Comicster.Searches.ComicAges".

For third-party plug-ins, we recommend a similar approach, except use your own name/company/project as the first part of the name. So if I were to publish a "third party" plug-in under the MadProps guise, I'd call it MadProps.Tools.Foo.dll or MadProps.Catalogs.Bar.dll.

File Format Plug-Ins

comicster-file-plugins-thumb.png

Comicster makes two interfaces available for you to implement custom file format for collections. They interfaces are located in the Comicster.IO namespace and look like this:

public interface ICollectionReader : ICollectionFileHandler
{
    /// <summary>
    /// The file extension (including the ".") used by this file format
    /// </summary>
    string Extension { get; }

    /// <summary>
    /// The Filter used in FileDialogs to represent this file format
    /// </summary>
    string Filter { get; }

    Collection ReadCollection(Stream stream);
}

public interface ICollectionReaderWriter: ICollectionReader
{
    void WriteCollection(Stream stream, Collection collection);
}

If you want to make a new "read only" file format plug-in (like the one used to open CMX files from the previous version), you only need to implement ICollectionReader so you can return a new Collection instance from the given stream.

If you want to be able to save to your custom file format, you should implement ICollectionReaderWriter and provide a way to write a collection to a stream too.

In order for the file format extension to show up in the Extension Gallery as a file format, the nupkg file's tags should include an "io" tag.

Catalog Plug-Ins

comicster-catalog-plugins-thumb.png

Comicster lets you search online catalogs and download item details in your collection. By default it ships with the ability to search its own online database (at Comicster.net). The interface that allows you to implement and define your own catalogs is in the Comicster.Catalogs namespace.

public interface ICatalog
{
    /// <summary>
    /// A unique key, used by Comicster to map local items to this
    /// catalog. A Uri (eg "http://example.com") is recommended.
    /// </summary>
    string Key { get; }

    /// <summary>
    /// A human-readable description of the catalog.
    /// </summary>
    string Name { get; }

    /// <summary>
    /// Indicates whether the catalog is read-only or allows for Comicster to
    /// save items to it. "Save" methods should throw a NotSupportedException if
    /// this property is true.
    /// </summary>
    bool IsReadOnly { get; }

    IEnumerable<Character> FindCharacters(string searchTerm);
    IEnumerable<Creator> FindCreators(string searchTerm);
    IEnumerable<Publisher> FindPublishers(string searchTerm);
    IEnumerable<Trade> FindTrades(string searchTerm);
    IEnumerable<Title> FindTitles(string searchTerm);
    IEnumerable<Issue> FindIssues(string titleSearchTerm, string number);
    IEnumerable<Issue> FindTitleIssues(string titleId, string number);

    Publisher GetPublisher(string id);
    Creator GetCreator(string id);
    Character GetCharacter(string id);
    Trade GetTrade(string id);
    Title GetTitle(string id);
    Issue GetIssue(string id);

    void SavePublisher(Publisher publisher);
    void SaveCreator(Creator creator);
    void SaveCharacter(Character character);
    void SaveTrade(Trade trade);
    void SaveTitle(Title title);
    void SaveIssue(Issue issue);
}

There's a lot to implement if you want to support all the different catalog types, but if you throw a NotSupportedException then Comicster will handle it gracefully and inform the user.

In order for the catalog extension to show up in the Extension Gallery as a catalog, the nupkg file's tags should include a "catalog" tag.

Search Plug-Ins

comicster-search-plugins-thumb.png

Comicster's Search page allows the user to search items in their collection using a plain text search, but also includes some "custom searches". You can add to the list of custom searches by implementing the ISearch interface found in the Comicster.Searches namespace:

public interface ISearch
{
    /// <summary>
    /// The text appearing in the list of custom searches for this search.
    /// </summary>
    string Text { get; }

    IEnumerable<Item> Execute(Collection collection);
}

This makes it trivially easy to add a custom search, because you're essentially just returning the results of a LINQ query over the collection object.

In order for the search extension to show up in the Extension Gallery as a search, the nupkg file's tags should include a "search" tag.

Tool Plug-Ins

comicster-tool-plugins-thumb.png

The most versatile kind of plug-in is the custom tool, which can effectively do anything you want. These plug-ins are found under the "Tools" menu, and Comicster discovers them by looking for classes that implements the ITool interface found in the Comicster.Tools namespace:

public interface ITool
{
    /// <summary>
    /// The text that will appear in the menu item for this tool.
    /// </summary>
    string Text { get; }

    bool CanExecute(IToolContext context);
    void Execute(IToolContext context);
}

Notice that the methods both accept a parameter of type IToolContext, which looks like this:

public interface IToolContext
{
    Collection Collection { get; }
    Item SelectedItem { get; }
    bool IsModified { get; }
    string FileName { get; }

    /// <summary>
    /// Sets the currently-active collection to a "modified" state so
    /// the user will be promted to save changes.
    /// </summary>
    void SetModified();
}

Additionally, if you need to implement a toggle tool, such as having on/off or enabled/disabled states which will display a checkmark in the left column of the menu choice, you can implement the IToogleTool interface and provide code for the IsChecked property.

public interface IToogleTool : ITool
{     
    bool? IsChecked { get; }
}

In order for the tool extension to show up in the Extension Gallery as a tool, the nupkg file's tags should include a "tool" tag.

Packaging and Uploading Your Extension to Comicster.net

Please refer to the "How to Package and Upload Your Extension" knowledge base article when you are ready to package and submit your extension.