Diese API Dokumentation gilt ergänzend zur XML-Dokumentation von .NET. Alle relevanten Members vom Namespace Namo.PluginCore sind mit entsprechenden XML-Tags versehen, welche in der IntelliSense von Visual Studio ersichtlich sind. Folgende Dokumentation beschreibt die Implementierung eines eigenen Plug-Ins in Prosa. Genaue Details zu den einzelnen Members können über die IntelliSense/Object Browser entnommen werden.
Eine MessageEngine stellt die Logik des Nachrichten Versenden zu Verfügung. Eine MessageEngine muss das Interface IMessageEngine implementieren. Einfacheitshalber wurde die abstrakte Klasse MessageEngineBase erstellt, welche IMessageEngine implementiert. Diese Klasse übernimmt bereits einige Logik, so dass folgende Dinge implementiert werden müssen:

Die meisten Properties sind "One-Liners" wie zum Beispiel MaxSmsLength wo lediglich ein Integer returniert werden muss, wie lange maximal ein SMS sein darf. Genaue Details zu den einzelnen Members sind mit der XML-Dokumentation von .NET Dokumentiert und darum vollständig in der Intelli-Sense von Visual Studio integriert. Bitte diese Dokumentation genaustens befolgen.
Ein Live-Feed muss folgendes Interface implementieren:
Das Herzstück eines Live-Feeds ist die Refresh-Methode. Diese Methode wird vom Host (genauer FeedHost) aufgerufen. Das Überprüfen ob Neuigkeiten vorhanden sind wird also in dieser Methode implementiert. Falls eine Nachricht geschickt werden muss, kann mit dem Property Message die zu verschickende Nachricht definiert werden. Anschliessend muss der Event FeedUpdateAvailable gefeuert werden, um dem Host mitzuteilen, dass eine neue Nachricht vorhanden ist. Als return value gibt man den Zeitpunkt, zu dem die Refresh Methode wieder aufgerufen werden soll.
Damit Live-Feeds nach einem Applikationsneustart wieder geladen werden können, muss deren Zustand serialisiert werden können. Dazu sind die beiden Methoden GenerateSettingsString bzw. LoadSettings verantwortlich. GenerateSettingsString liefert einen String aller Einstellungen, welche der Methode LoadSettings zum laden wieder übergeben werden. Die Praxis hat gezeigt, dass man hier am besten ein Settings-Objekt erstellt und mit dem XmlSerializer einen XML-String erzeugt.
Die Validate wird immer vor dem Speichern der Einstellungen aufgerufen. So kann das Live-Feed die Eingaben des Benutzers validieren.
Die HttpRequest Klasse vereinfacht das GET bzw. POST (auch Multipart für Bilder) Requests abzusetzen. Folgend ein Beispiel:
var request = new HttpRequest();
request.AddPostData("key1", "value1");
request.AddPostData("key2", "value2");
request.GetData("http://www.namo-sms.ch/http_request_demo.php");
Console.WriteLine(request.HtmlReturn); // Ausgabe des HTML auf die Konsole
Jedes Plug-In hat ein Property Host vom Typ INamoHost. Dieses Interface stellt folgende Methode zur Verfügung.
public interface INamoHost
{
void WriteLog(string log, LogLevel level);
}
Mit dieser Methode kann das Plug-In Meldungen an den Host senden. Beim Namo SMS Client erscheinen diese auf der Error Konsole.
//-----------------------------------------------------------------------
// <copyright file="UrlWatcher.cs" company="Namo SMS">
// Copyright (c) Namo SMS. All rights reserved.
// </copyright>
// <author>
// Tobias Zürcher tobi@namo-sms.ch
// </author>
//-----------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Namo.PluginCore;
using Namo.PluginCore.LiveFeed;
using Namo.PluginCore.Tools;
namespace Namo.LiveFeed.UrlWatcher
{
public class UrlWatcher : ILiveFeed
{
private Page _settingsPage;
private BitmapSource _image;
public event EventHandler FeedUpdateAvailable;
#region Properties
public string Name
{
get { return "UrlWatcher"; }
}
public string Description
{
get { return "Dieses Plug-In überwacht eine URL und benachrichtigt bei einer Änderung"; }
}
public string Author
{
get { return "www.namo-sms.ch"; }
}
public string Contact
{
get { return "team@namo-sms.ch"; }
}
public ImageSource Image
{
get
{
if (_image == null)
{
try
{
_image = Imaging.CreateBitmapSourceFromHBitmap(
Properties.Resources.LiveFeedIcon.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
catch
{
_image = null;
}
}
return _image;
}
}
public string Version
{
get { return "1.0.0"; }
}
public Page SettingsPage
{
get
{
if (_settingsPage == null)
_settingsPage = new Settings(Settings);
return _settingsPage;
}
}
public UrlWatcherSettings Settings { get; set; }
public string Message { get; set; }
public string Identification
{
get
{
return "Namo.LiveFeed.UrlWatcher.dll";
}
}
public INamoHost Host { get; set; }
#endregion
public UrlWatcher()
{
Settings = new UrlWatcherSettings();
}
public DateTime Refresh()
{
var req = new HttpRequest();
req.GetData(Settings.Url);
if (req.HtmlReturn != Message)
{
// Angesurfte Seite hat unterschied
Message = req.HtmlReturn; // message aktualisieren
// event feuern -> löst das SMS versenden im Host aus
OnLiveFeedUpdateAvailable(EventArgs.Empty);
}
else
{
Debug.WriteLine("UrlWatcher::Refresh: nothing new");
}
// return wann wir als nächstes mal aktualisieren möchten
return DateTime.Now.AddSeconds(Settings.Interval);
}
public string GenerateSettingsString()
{
return "url=" + Settings.Url + ";interval=" + Settings.Interval;
}
public void LoadSettings(string settings)
{
if (settings != null)
{
var rgx = new Regex(@"url=(?<url>\S*);interval=(?<interval>\S*)");
Settings.Url = rgx.Match(settings).Groups["url"].Value;
int interval;
Int32.TryParse(rgx.Match(settings).Groups["interval"].Value, out interval);
Settings.Interval = interval;
}
}
public bool Validate()
{
// keine Validierung implementiert
return true;
}
protected void OnLiveFeedUpdateAvailable(EventArgs args)
{
if (FeedUpdateAvailable != null)
FeedUpdateAvailable(this, args);
}
}
}