Since today I posted my Facebook widget on this site(turned out it actually was the second, but oh well - mine is better
- not meant to be rude rtur, I've seen and appreciate the work you did for Blogengine.net) I decided to elaborate a bit on the design I picked for implementing it. My main concern was to keep all code for working with the settings in one place, not spread out over multiple classes. See the point with Blogengine.Net widgets is that there are (obviously) specifications:
- There may only two controls, widget and edit, and they live in the same folder
- Those controls use code behind files, so total is 4 files:widget.ascx, widget.ascx.cs, edit.widget.ascx, edit.ascx.cs
- The Widget Class must extend WidgetBase and override the Name and isEditable properties, and the LoadWidget method
- The Edit class must extend WidgetEditBase and override Save method
That's it in a nutshell. I won't elaborate more since this is all documented on the Blogengine.net site. Now add the following points:
- It deviates from the normal way of doing things to add more classes/folders to other locations - who needs change anyway?
- It's bad practise to put stand alone class files outside the App_Code folder
Still, I want an extra class for the data, and put it neatly in place...now what?
My solution

That's right, I made a singleton class FaceBookData, and nested it in the Edit class. Now to make the FaceBookData be able to access the GetSettings() method, I put the behavior in an interface that I nested in the same namespace as my Widget and Edit classes:
/// <summary>
/// Interface for the GetSettings() behavior of both WidgetEditBase and WidgetBase
/// </summary>
public interface IFaceBookData
{
StringDictionary GetSettings();
}
Now the data class can use the method, no matter which method calls the singleton "getInstance" method first. For the save method no interface is needed, since only WidgetEditBase has a SaveSettings() method. One important thing not to forget is to add a reference in the widget.ascx f
<%@ Control Language="C#" AutoEventWireup="true"
CodeFile="Widget.ascx.cs" Inherits="Widgets.FaceBook.Widget" %>
<%@ Reference Control="~/widgets/Facebook/Edit.ascx" %>
And that's it! You have your very own singleton data loading/saving class for your widget!
Very nice Rene, but what on earth is a singleton?
Ah valid question I guess. A singleton is a class of which only one instance can be alive at each and every moment. So they're a bit like Elvis. There can only be one of them. Besides, who wants two Elvisses?
What are they used for? Well if you really wanna be darn sure there is only one instance of the to be singleton class lingering around in your application. Think of loggers, file managers, database connectors...etc.
How to make one? The standard way of doing this is by creating a private field of the classes type, set the constructor to private, and make some getInstance() method.(quite foolproof, but can be broken using reflection, I won't cover that here) Example following the Elvis idea:
public class Elvis
{
private static Elvis instance = null;//here we store Elvis
private Elvis()//nobody except this class can call the constructor now!
{
//your constructor logic
}
public static Elvis GetInstance()//static, so it can be called without an instance reference
{
if (instance == null)//if Elvis isn't here
{
instance = new Elvis();//then GET him
}
return instance;//return Elvis
}
}
The reason in this case why you always want one, is to make really really sure both Widget and Edit are reading from the same object.
Now in the case of this widget, it looks like this, there's a whole lot of stuff added, but in basics it does the same!
public class FaceBookSettings
{
#region Properties
private static FaceBookSettings instance = null;
private IFaceBookData source;
/// <summary>
/// The URL to the Facebook page
/// </summary>
public string FacebookURL { get; set; }
/// <summary>
/// Width of the box in pixels
/// </summary>
public string Width { get; set; }
/// <summary>
/// Height of the box in pixels
/// </summary>
public string Height { get; set; }
/// <summary>
/// Colorscheme to use(light/dark)
/// </summary>
public string ColorScheme { get; set; }
/// <summary>
/// HTML color for the border(optional)
/// </summary>
public string BorderColor { get; set; }
/// <summary>
/// boolean value to show small icons of people who liked
/// </summary>
public string ShowFaces { get; set; }
/// <summary>
/// boolean value to show the stream of comments on the wall of the page
/// </summary>
public string ShowStream { get; set; }
/// <summary>
/// boolean value to show the header
/// </summary>
public string ShowHeader { get; set; }
#endregion
#region private constructor
private FaceBookSettings(IFaceBookData source)
{
this.source = source;
this.LoadSettings();
}
#endregion
#region public methods
/// <summary>
/// Gets the singleton instance of FaceBookSettings
/// </summary>
/// <param name="source">IFaceBookData element that called the method(probably a this ref)</param>
/// <returns>The singleton instance of settings are loaded and returned</returns>
public static FaceBookSettings getSettings(IFaceBookData source)
{
if (instance == null)
{
instance = new FaceBookSettings(source);
}
return instance;
}
/// <summary>
/// Saves the settings
/// <remarks>Only abstract class WidgetEditBase contains a SaveSettings method, hence this method
/// can only be called by FaceBook.Edit</remarks>
/// </summary>
/// <param name="source">FaceBook.Edit caller(probably a this ref)</param>
public void SaveSettings(FaceBook.Edit source)
{
var settings = source.GetSettings();
settings["facebookurl"] = this.FacebookURL;
settings["width"] = this.Width;
settings["height"] = this.Height;
settings["colorscheme"] = this.ColorScheme;
settings["bordercolor"] = this.BorderColor;
settings["showfaces"] = this.ShowFaces;
settings["showstream"] = this.ShowStream;
settings["showfaces"] = this.ShowHeader;
source.SaveSettings(settings);
}
#endregion
#region methods
private void LoadSettings()
{
var settings = this.source.GetSettings();
this.FacebookURL = (settings.ContainsKey("facebookurl")) ? settings["facebookurl"] : @"http://www.facebook.com/platform";
this.Width = (settings.ContainsKey("width")) ? settings["width"] : "240";
this.Height = (settings.ContainsKey("height")) ? settings["height"] : "427";
this.ColorScheme = (settings.ContainsKey("colorScheme")) ? settings["colorScheme"] : "light";
this.BorderColor = (settings.ContainsKey("borderColor")) ? settings["borderColor"] : "";
this.ShowFaces = (settings.ContainsKey("showFaces")) ? settings["showFaces"] : "true";
this.ShowStream = (settings.ContainsKey("showStream")) ? settings["showStream"] : "false";
this.ShowHeader = (settings.ContainsKey("showHeader")) ? settings["showHeader"] : "true";
}
If you got this far reading, congratulations! Full source code can be found over here!