Visual Rx – Part 6

2012/10/25

Visual Rx – Part 6

this post is part of the Visual Rx series and it will focus on Visual Rx Viewer Side Extensibility.

this post is dealing with advance topic, you may want to read other post on this series before reading this one.

Rx, Reactive, LINQ, Minitor, Monitoring, Profile, Trace, Viewer, Tool, Extensibility

this post refer to version 2.0.20.622.60 or higher (the extensibility model was simplify at this version).

Visual Rx support extension via plug-ins bundle contract.
a plug-ins bundle contains:

  • General information about the package (like title and description),
  • Publisher information (like name, email and web address)
  • Implementation for different plug-ins capabilities.

plug-ins capabilities can be one or more implementation for the following aspects:

a complete Tab (actually the Grid Tab is a plug-in that you can remove).

Rx, Reactive, LINQ, Minitor, Monitoring, Profile, Trace, Viewer, Tool, Extensibility

It can modify a marble diagram icon.

Rx, Reactive, LINQ, Minitor, Monitoring, Profile, Trace, Viewer, Tool, Extensibility

and even change the representation of single item:

Rx, Reactive, LINQ, Minitor, Monitoring, Profile, Trace, Viewer, Tool, Extensibility

it can also control the entire view of a marble diagram (this way you can control the entire diagram view).

Rx, Reactive, LINQ, Minitor, Monitoring, Profile, Trace, Viewer, Tool, Extensibility

you can see the code of this extension in the source code under the StockExchangeGraphPlugin project.

the last extensibility point is a non visual extensibility. 
it can intercept an item and do what ever you want to do with it data (for example send an email or write to a file).

How to get started?

first you have to set a plug-in bundle.
as I said earlier a bundle encapsulate the information about the plug-in and the publisher with a set of plug-in’s capabilities.

it is done by inheritance of the PluginBundleBase class which is implementing the IPluginBundle interface (if you want you can inherit the interface directly).

the following is the IPluginBundle definition:

Code Snippet
  1. public interface IPluginBundle
  2. {
  3.     Guid Id { get; }
  4.     string Title { get; }
  5.     string Description { get; }
  6.     Version Version { get; }
  7.     string PublisherName { get; }
  8.     string PublisherEmail { get; }
  9.     string SupportUrl { get; }
  10.     string ProductUrl { get; }
  11.     ImageSource Icon { get; }
  12.  
  13.     bool HasCustomConfiguration { get; }
  14.     void EditConfiguration();
  15.  
  16.     IItemInterceptionPlugin InterceptionPlugin { get; }
  17.     ILineHeaderImagePlugin LineHeaderImagePlugin { get; }
  18.     IMarblePanelPlugin MarblePanelPlugin { get; }
  19.     IMarbleItemPlugin MarbleItemPlugin { get; }
  20.     ILoadResourcesPlugin LoadResourcesPlugin { get; }
  21.     ITabPlugin TabPlugin { get; }
  22. }

as you can see it start with information  about the plug-in and the publisher and followed by a set of properties which return interfaces.
those interfaces represent different capabilities.

let start with the most general interface which is helping the plug-in environment rather then actually having a real plug-in functionality.

Load Resources Plugin

the LoadResourcesPlugin property return the ILoadResourcesPlugin interface. this is how you can add resources which can be latter used by other plug-ins implementation (it is very common that your plug-in representation will need resources which is not available within Visual Rx core).

for example you can load WPF ResourceDictionary which will contain anything needed by your plug-in (images, styles, templates, ext.).

Code Snippet
  1. public class LoadResourcesPlugin : ILoadResourcesPlugin
  2. {
  3.     private readonly string ASSEMBLY_NAME = UIPluginHelper.GetAssemblyName();
  4.  
  5.     public ResourceDictionary[] GetResources()
  6.     {
  7.         Uri uri = UIPluginHelper.GetResourceUri(ASSEMBLY_NAME, "CustomMarble.xaml");
  8.         ResourceDictionary myResource = new ResourceDictionary();
  9.         myResource.Source = uri;
  10.         return new ResourceDictionary[] { myResource };
  11.     }
  12. }

as you can see Visual Rx does have some helper method like UIPluginHelper.GetAssemblyName() which can make this task even easier.

Marble Item Plugin

the must useful capability may be the ability to change the item representation based on it’s data.
this capability achieved by implementation of the MarbleItemPlugin property which return the IMarbleItemPlugin interface.

the interface is fairly simple and it look as follow:

Code Snippet
  1. public interface IMarbleItemPlugin
  2. {
  3.     DataTemplate SelectTemplate(MarbleBase item, FrameworkElement element);
  4. }

it gets an item and a FrameworkElement and return a DataTemplate.
you should return null if you don’t want to change the default template for the current item.

the following snippet was taken from the System.Reactive.Contrib.Monitoring.SamplePlugin which is part of the source code that available for download at codeplex.

Code Snippet
  1. public class PseudoTemplateSelectorPlugin : IMarbleItemPlugin
  2. {
  3.     public DataTemplate SelectTemplate(MarbleBase item, FrameworkElement element)
  4.     {
  5.         DataTemplate template = null;
  6.         bool startWith = item.Name.ToLower().StartsWith("sec");
  7.         bool isDivBy10 = Convert.ToInt32(item.RawValue) % 10 == 0;
  8.         if (startWith && isDivBy10)
  9.         {
  10.             template = element.FindResource("CustomMarbleNextTemplate") as DataTemplate;
  11.         }
  12.         return template;
  13.     }
  14. }

the above implementation is replacing the template for items within marble diagrams that start with "sec" and ignoring items that doesn’t divide by 10.
the result will be the fire icon representation for those items:

Rx, Reactive, LINQ, Minitor, Monitoring, Profile, Trace, Viewer, Tool, Extensibility

Line Header Image Plugin

sometime all you want to do is to change the marble diagram icon.
in this case you should use the LineHeaderImagePlugin property which return the ILineHeaderImagePlugin interface.

Code Snippet
  1. public interface ILineHeaderImagePlugin
  2. {
  3.     ImageSource Convert(string text);
  4. }

the text parameter is the name of the marble diagram.
it can be use as follow (taken from the System.Reactive.Contrib.Monitoring.SamplePlugin):

Code Snippet
  1. public class ImageMapperPlugin : ILineHeaderImagePlugin
  2. {
  3.     private static readonly string ASSEMBLY_NAME = UIPluginHelper.GetAssemblyName();
  4.     private readonly Uri STRESS_IMG = UIPluginHelper.GetPackResourceUri(ASSEMBLY_NAME, "Images/clicknrun.png");
  5.     private readonly Uri SEC_IMG = UIPluginHelper.GetPackResourceUri(ASSEMBLY_NAME, "Images/Clock.png");
  6.  
  7.     public ImageSource Convert(string text)
  8.     {
  9.         text = text.ToLower();
  10.         ImageSource img = null;
  11.         if (text.StartsWith("stress"))
  12.             img = new BitmapImage(STRESS_IMG);
  13.         else if (text.StartsWith("sec"))
  14.             img = new BitmapImage(SEC_IMG);
  15.         return img;
  16.     }
  17. }

the above snippet is changing the icons of the stress and sec marble diagrams into a preloaded resource (see LoadResourcesPlugin) and ignore any other diagrams.

the result will be shown as follow:

Rx, Reactive, LINQ, Minitor, Monitoring, Profile, Trace, Viewer, Tool, Extensibility

as you can see the sec icons become a clock,  stress become runner while the error icon remain the default one.

I will leave the rest of the plug-in capabilities to a latter post and switch into the plug-in deployment.

Plug-in Deployment

the plug-in are exposed though MEF (when you implement IPluginBundle or inherit PluginBundleBase your code is automatically exported).

the Visual Rx setting let you set the plug-ins discovery and activation.

Rx, Reactive, LINQ, Minitor, Monitoring, Profile, Trace, Viewer, Tool, Extensibility

the following diagram is showing the setting dialog:

Rx, Reactive, LINQ, Minitor, Monitoring, Profile, Trace, Viewer, Tool, Extensibility

the plug-in setting is divided into 2 sections:

  • discovery section where you can set plug-in folders (both relative and absolute path are supported).
  • plug-in activation section where you can enable or disable plug-ins.
Future features

the setting dialog will have a plug-in upload and download from a central plug-in repository.

each plug-in will also be able to add a custom setting.

summary

Visual Rx was built for extensibility.
you can use built-in, your own or 3rd party plug-ins which may enhance your monitoring efficiency.

Sample code

the sample code is part of the source code of Visual Rx.
you can use the sample as a starting point but remember that it is only a sample code, some of the sample has a memory leak and other issues.
you should test the code as you would test your own code.

kick it on DotNetKicks.com Shout it

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*