This section explains how to create an extension point.
Defining an Extension Point
An extension point is defined by creating an attribute class, which extends the extension attribute base class, ExtensionAttribute. The properties of this attribute class define the meta-data extension developers can provide with their extensions.
Extension developers can now create an extension .Net class, and mark this up with the extension attribute to indicate which extension point it targets.
Going back to the example, in order to allow message transmitters to be plugged in, we need to define an extension point. This is done by defining an extension attribute class, MessageTransmitterAttribute, which extends the extension attribute base class, ExtensionAttribute:
[ExtensionPointInfo("Message Transmitters", ExtensionPointTypes.Static)] public class MessageTransmitterAttribute : ExtensionAttribute { private double _costPerCharacter; /// <summary> /// Constructor for XML serialization /// </summary> public MessageTransmitterAttribute() { } /// <summary> /// Constructor using basic properties. /// </summary> public MessageTransmitterAttribute(string id, string name, string description) : base(id, name, description) { } /// <summary> /// Gets or sets the cost in dollar per character in the message. /// </summary> public double CostPerCharacter { get { return _costPerCharacter; } set { _costPerCharacter = value; } } /// <summary> /// Validates that the extension implements the IMessageTransmitter interface. /// </summary> /// <param name="info"></param> /// <param name="context"></param> public override void Validate( Sdl.Core.PluginFramework.Validation.IExtensionAttributeInfo info, Sdl.Core.PluginFramework.Validation.IExtensionValidationContext context) { base.Validate(info, context); context.ValidateRequiredInterface(typeof(IMessageTransmitter)); } }
The purpose of the message transmitter attribute is to allow plug-in developers to use it to annotate their message transmitter extension classes, to make them known as message transmitter implementations to the extension point.
In order to make the attribute an extension point, we have to annotate with the ExtensionPointInfoAttribute attribute, which specifies the name and type of the extension point. The name can be used by a plug-in manager UI to represent the extension point. The type can be either static or dynamic, referring to whether this extension point allows enabling or disabling of one or more of it’s extensions without having to restart the application. More on that later.
The ExtensionAttribute class has the following properties, providing meta data about the extension:
- Id: A unique id for the extension
- Name: A friendly name for the extension.
- Description: A description of the extension.
- Icon: An optional icon representing the extension.
Note that we have defined an extra property, CostPerCharacter, which indicates the cost in dollar for each character sent in a message.
Since all these properties will be extracted to the plug-in manifest file by the plug-in manifest generator, the host application will be able to access their values without having to create an instance of the actual transmitters or even load the plug-in assembly. Since the plug-in manifest generator uses XML serialization to save the attribute information, the attribute has have a default, parameterless constructor.
We still have to define which functionality is required from an extension class to be accepted as a valid message transmitter by the host application. This is done by defining an interface:
using System; using System.Collections.Generic; using System.Text; namespace Sdl.TranslationStudio.Sdk.Documentation.Samples { #region IMessageTransmitter public interface IMessageTransmitter { void SendMessage(string message); } #endregion IMessageTransmitter }
This simple interface contains one method, SendMessage, to be called by the host application to send the message.
Extension points can also define validation functionality which is used by the framework at compile-time to validate its extensions. In the example, tye extension point checks whether the extension implements the IMessageTransmitter interface. If an extension ndoes not implement this interface, an error will be generated at compile time. For more information on extension validation see Compile-time Validation.
We define both the MessageTransmitterAttribute and the interface in an assembly, called ExtensionPointDefinitions, so it can be references by the host applications and by plug-in assemblies.
Next, we can start creating an extension that targets our new extension point in Creating Extensions.