Friday, December 14, 2007

BulgarianException

Hi all, here is an example implementation for a Bulgarian Exception.
Have nice time in the new year's eve and avoid this exception ;)

[Serializable]
class BulgarianException
   : ApplicationException
{
   [field: NonSerialized]
   const ulong MIN_ALLOWED_GRAMS_RAKIA = 500;
   [field: NonSerialized]
   const ulong MIN_ALLOWED_GRAMS_WEIN = 1000;
   [field: NonSerialized]
   const ulong MIN_ALLOWED_GRAMS_BEER = 20 * 500; //1 kasa
   [field: NonSerialized]
   const ulong MIN_ALLOWED_GRAMS_SHOPSKA_SALAD = 5 * 1000;
   [field: NonSerialized]
   const ulong MIN_ALLOWED_GRAMS_MEZETA = 10 * 1000;

   private ulong mGramsRakia;
   private ulong mGramsWein;
   private ulong mGramsBeer;
   private ulong mGramsShopskaSalad;
   private ulong mGramsMezeta;

   public ulong GramsRakia
   {
      get { return this.mGramsRakia; }
   }
   public ulong GramsWein
   {
      get { return this.mGramsWein; }
   }
   public ulong GramsBeer
   {
      get { return this.mGramsBeer; }
   }
   public ulong GramsShopskaSalad
   {
      get { return this.mGramsShopskaSalad; }
   }
   public ulong GramsMezeta
   {
      get { return this.mGramsMezeta; }
   }

   public BulgarianException(ulong pGramsRakia, ulong pGramsWein, ulong pGramsBeer, ulong pGramsShopskaSalad, ulong pGramsMezeta, string pMessage, Exception pInnerException)
      : base( pMessage, pInnerException)
   {
      this.mGramsRakia = pGramsRakia;
      this.mGramsWein = pGramsWein;
      this.mGramsBeer = pGramsBeer;
      this.mGramsShopskaSalad = pGramsShopskaSalad;
      this.mGramsMezeta = pGramsMezeta;
   }

   public BulgarianException(string pMessage, Exception pInnerException)
      : this(0, 0, 0, 0, 0, pMessage, pInnerException)
   {
   }

   public BulgarianException(string pMessage)
      : this(pMessage, null)
   {
   }

   public string GenericMessage
   {
      get
      {
         StringBuilder message = new StringBuilder();
         message.Append(this.Message);
         message.Append("\nInsufficient alcoholic/nutritious resources:\n");

         if (mGramsRakia < MIN_ALLOWED_GRAMS_RAKIA)
         {
            message.Append(string.Format("Rakia: {0}, should be: {1}\n", mGramsRakia, MIN_ALLOWED_GRAMS_RAKIA));
         }

         if (mGramsWein < MIN_ALLOWED_GRAMS_WEIN)
         {
            message.Append(string.Format("Wein: {0}, should be: {1}\n", mGramsWein, MIN_ALLOWED_GRAMS_WEIN));
         }

         if (mGramsBeer < MIN_ALLOWED_GRAMS_BEER)
         {
            message.Append(string.Format("Beer: {0}, should be: {1}\n", mGramsBeer, MIN_ALLOWED_GRAMS_BEER));
         }

         if (mGramsShopskaSalad < MIN_ALLOWED_GRAMS_SHOPSKA_SALAD)
         {
            message.Append(string.Format("Shopska salad: {0}, should be: {1}\n", mGramsShopskaSalad, MIN_ALLOWED_GRAMS_SHOPSKA_SALAD));
         }

         if (mGramsMezeta < MIN_ALLOWED_GRAMS_MEZETA)
         {
            message.Append(string.Format("Mezeta: {0}, should be: {1}\n", mGramsMezeta, MIN_ALLOWED_GRAMS_MEZETA));
         }

      return message.ToString();
      }
   }
}

...

if (DateTime.Now.Equals(new DateTime(2007, 12, 31, 23, 59, 59))
   && (rakia < recommended_rakia
      || wein < recommended_wein
      || beer < recommended_beer
      || salad < recommended_salad
      || meze < recommended_meze))
{
   throw new BulgarianException(rakia, wein, beer, salad, meze, "Oh, come on! It's new year, dude!!!", null);
}

Friday, December 7, 2007

Adding plugin support for your apps - Part 1

Hi guys, as I promised, I'm posting the easiest way to add plugin support for your application.
This is done in 3 simple steps.

Step 1. Creating universal interface for all plugins.
This should be done by creating a class library and add an interface. In this case, I'm adding 2 functions - one for initializing and one for calculating. Compile the class library.


public interface IPlugin
{
double Eval(double a, double b);
void Initialize();
}

Tip: Do not put the interface in a namespace. This would spare you some string symbols later ;)

Step 2. Creating a Plugin.
The plugin itself should be a class library, too. The main class in it, should implement the IPlugin interface from Step 1. Dafür, add a reference to the compiled class library and implement it.


public class Sum : IPlugin
{
public double Eval(double x, double y)
{
return x + y;
}

public void Initialize()
{
MessageBox.Show("Plugin loaded: " + Assembly.GetExecutingAssembly().FullName, "Plugin Message");
}
}

In this case, the initialize method shows a message box, and the Eval method - sums up two numbers.

Step 3. Adding the support to the application and loading the available plugins.
This happens in the main application. Let's say we have defined a directory for the plugins and it is the sub dir "plugins" of the main directory. We can search it up for any plugins.

First we define a collection, which will store all loaded plugins...

List<IPlugin> Plugins = new List<IPlugin>();

...and the load them...

string Path = Assembly.GetExecutingAssembly().Location.Substring(0, Assembly.GetExecutingAssembly().Location.LastIndexOf(@"\") + 1) + @"plugins\";
//getting all .dll files in plugins dir
string[] DLLs = Directory.GetFileSystemEntries(Path, "*.dll");
foreach (string DLL in DLLs)
{
Assembly AssemblyDLL;
try
{
AssemblyDLL = Assembly.LoadFrom(DLL);

foreach (Type objType in AssemblyDLL.GetTypes())
{
//Only look at public types
if (objType.IsPublic)
{
//Ignore abstract classes
if ((objType.Attributes & TypeAttributes.Abstract) != TypeAttributes.Abstract)
{
//See if this type implements our interface
Type objInterface = objType.GetInterface("IPlugin", true);
if (objInterface != null)
{
//instanciating
IPlugin PluginInstance = (IPlugin)AssemblyDLL.CreateInstance(objType.FullName);
//calling initialize method
PluginInstance.Initialize();
//adding it to the collection
Plugins.Add(PluginInstance);
}
}
}
}
}
catch (Exception e)
{
//Error loading DLL, we don't need to do anything special
System.Diagnostics.Trace.WriteLine(e.Message);
continue;
}
}

How to test it? Well, let's do some maths here :)

foreach(IPlugin plugin in Plugins)
{
MessageBox.Show(plugin.Eval(2d, 2d).ToString());
}