inheritable singleton pattern for windows forms

Hello!

I'm rather new to C# and developing my first commercial application in that language. It contains some forms, and only one instance of each form can exist in the running application. So, each form implements the Singleton pattern is such way:

public class Report: Form {

private static Report _instance;

protected Report(){InitializeComponent(); ... }

public static Form instance {get {

if (_instance == null) _instance = newReport();

return _instance;}}

...

}

So, this code is duplicated in every single form in my application and the only difference between forms is shown inbold in the example. I want to get rid of that duplication, for example, by defining a base clase which inherits Form and implements Singleton behaviour.

As creating virtual static method, which could return

typeof(corresponding_form_class)

is impossible in C#, I tried to use generics:

public class SingletonForm: Form<T> where T: Form, new() {

private static T _instance;

protected SingletonForm(){}

public static T instance {get {

if (_instance == null) _instance = new T();

return _instance;}}

...

}

And then defining concrete form classes this way (looks weird):

public class ConcreteForm: SingletonForm<ConcreteForm>{

...

}

It compiles and runs, but when I try to open Concrete form in the IDE designer, I receive an error message that says that the base class cannot be loaded.

And this is where I am now. Waiting for clues from experienced C# programmers :)

[2983 byte] By [valentin_lv] at [2007-12-23]
# 1
The problem is with design-time support for generics. A crude and ugly workaround is to have commented out declaration for your form that you uncomment when you want to edit the form in the designer, i.e.:

public class ConcreteForm : SingletonForm<ConcreteForm>
// public class ConcreteForm : Form
{
...
}

When you want to edit the form in the designer, you switch the comment to the other declaration, i.e.:

//public class ConcreteForm : SingletonForm<ConcreteForm>

public class ConcreteForm : Form

{

...

}

If there is a more elegant workaround to this, I would also be very interested in knowing what it is.

RabbiJosephGordon at 2007-8-30 > top of Msdn Tech,.NET Development,.NET Base Class Library...
# 2
A completely different approach is to have one "authority" to hand out instances to forms:

static class FormProvider

{

static Dictionary<Type, Form> lookup = new Dictionary<Type,Form>();

static public Form GetInstance(Form owner, Type t)

{

// Return singleton instance if already created

if (lookup.ContainsKey(t)) return lookup[t];

// Create new instance

Form f = (Form)Activator.CreateInstance(t);

lookup.Add(t, f);

f.Owner = owner;

f.FormClosed += new FormClosedEventHandler(remover);

f.Show();

return f;

}

static private void remover(Object sender, FormClosedEventArgs e) {

// Remove form instance from <lookup>

lookup.Remove(sender.GetType());

}

}

And use it like this:

private void button1_Click(object sender, EventArgs e)

{

Form2 f = (Form2)FormProvider.GetInstance(this, typeof(Form2));

}

It is all still pretty awkward, you can't escape the cast and the owner

argument is difficult if you try to call GetInstance from a non-form

class.

VB.NET has the My.Forms collection, strongly typed too. Lucky

dogs. But it takes a designer to create the required design-time

code.

Hope it gives you some ideas...

nobugz at 2007-8-30 > top of Msdn Tech,.NET Development,.NET Base Class Library...
# 3

Thank you!

I also kept this different approach in reserve.

But now, when I see how easy the implementation is using the Dictionary class, I'll use it.

But, of course, it would be nice for MS developers to get the Form Designer work correctly.

valentin_lv at 2007-8-30 > top of Msdn Tech,.NET Development,.NET Base Class Library...
# 4
IMHO this is just more an implementation of a factory desing pattern

using a hashmap:
www.oodesign.com/Singleton
www.oodesign.com/Factory

As I know there is no inheritable singleton and there are

some limitations for this. If you need a such thing then use the

factory method.

I think this is the major drawbak of the singleton, that can not be

inheritable, because the singleton class name itself is used to get the

instance:

Singleton.GetInstance().

I would say that Singleton.GetInstance("type") is can be as well a

Factory.GetInstance("type"). This is just a combination of those 2

patterns.

adiian at 2007-8-30 > top of Msdn Tech,.NET Development,.NET Base Class Library...

.NET Development

Site Classified