 |
|
 |
Btw this is a great implementation and it works great. However I have found that when trying to apply it to forms it has a problems. When I close a form the object gets disposed but when I want to open the form again it refers to the disposed object instead of creating a new one. Is there something else that could be add that will make it do that? I know i could just hide the forms instead of closing them but that sounds messy.
|
|
|
|
 |
|
 |
I have the same problem. This is a draft of my solution.
Sorry, it's te bad code first pattern and in vb.net, but you can get the idea
Public Class FormSingletonProvider(Of itemtype As {New, System.Windows.Forms.Form})
Public Sub New()
End Sub
Private Shared _instance As itemtype = Nothing
Public Shared ReadOnly Property Instance() As itemtype
Get
If _instance Is Nothing OrElse _instance.IsDisposed Then
_instance = New itemtype
End If
Return _instance
End Get
End Property
End Class
|
|
|
|
 |
|
 |
Here's a special implementation of this that I came up with that handles anything deriving from Control differently than anything else. It's a little bit better than the other guy's implementation, IMHO, because it uses reflection to allow a single class to handle both disposable control types as well as anything else. You just have to be your own judge of whether the performance hit of a tiny bit of reflection scares you or not.
public class Singleton where T : new()
{
static private T _instance;
static public T Instance
{
get
{
if (_instance is Control)
{
Type t = typeof(T);
if ((bool)t.GetProperty("IsDisposed").GetValue(_instance, null))
_instance = default(T);
}
if (_instance == null)
_instance = new T();
return _instance;
}
}
}
|
|
|
|
 |
|
 |
If you have a need to dispose an object and recreate it again, you shouldn't use the singleton design pattern in the first place. It is not meant for use in the scenario that you describe!
If you need to hold onto a reference to an object that should automatically become null/Nothing when the object goes away, you should have a look at the WeakReference class.
Regards,
Gerke.
|
|
|
|
 |
|
 |
Thanks Lusid Insanity I'll give it a try.
Gerke does that solution keep only one instance of my form open? The thing is I want to only allow one open at a time.
|
|
|
|
 |
|
 |
If you use the singleton pattern with the reference to your form stored in a WeakReference field, you ensure you have no more than one form active, but the form is not kept alive by the singleton. Here is a code sample to get you started, though I still would have strong doubts about any design that requires this monster... namespace WeakSingletonDemo { using System; using System.Diagnostics; using System.Threading; public class WeakSingleton<T> where T: class, new() { private static WeakReference _instance = new WeakReference(null); private static object _instanceLock = new object(); public static T Instance { get { T result = (T) _instance.Target; if (result == null) { lock (_instanceLock) { result = (T) _instance.Target; if (result == null) { result = new T(); _instance.Target = result; } } } return result; } } } class Program { private class Message { private static int _nextMessageId = 1; public readonly string Text = string.Format("Message #{0}.", _nextMessageId++); } static void Main(string[] args) { Message firstMessage = WeakSingleton<Message>.Instance; string firstMessageText = firstMessage.Text; GC.Collect(); Debug.Assert(WeakSingleton<Message>.Instance.Text == firstMessageText, "Message singleton has not released during garbage collection, because strong references still exist."); firstMessage = null; GC.Collect(); Debug.Assert(WeakSingleton<Message>.Instance.Text != firstMessageText, "Message singleton has been released during garbage collection, because there were no strong references left."); } } } Regards, <a href = "http://www.geurtsrus.com/gerke" rel="nofollow">Gerke</a>.
|
|
|
|
 |
|
 |
If I have a series of objects that are all derived from the same base call how would I go about using SingletonProvider to create instances of the derived classes on the fly at run time. I'd envision a method similar to:
private void x(string GenericClassName)
{
GenericClass y = SingletonProvider.Instance;
y.DoSomething();
}
But I can't find a way to make this happen. Any advice would be appreciated.
Thanks,
JK
|
|
|
|
 |
|
 |
Creating types on the fly simply means extremely bad design. I cant think of any situation that requires you creating types on the fly. If still you are in need of such then you can try this:
declare the Singleton classes for every class you may require and use a switch statement to decide which one to instantiate
|
|
|
|
 |
|
|
 |
|
 |
Ive only used c# sharp a little and found this article v. helpful for my project as I hadnt encountered generics before it.
Here is the code I generated, does anyone know of a better way than using the lock?
This method prevents you from using the new keyword on a class that must always be a singleton.
using System;
using System.Collections.Generic;
using System.Text;
namespace AIBG
{
public class Singleton where T : new()
{
private static T instance = new T();
private static readonly object padlock = new object();
public static T Instance
{
get
{
lock (padlock)
{
if (instance == null) instance = new T();
}
return instance;
}
}
protected Singleton()
{
if (instance != null)
{
throw (new Exception("You have tried to create a new singleton class where you should have instanced it. Replace your \"new class()\" with \"class.Instance\""));
}
}
}
public class MySingletonClass:Singleton {
public void scream() {
Console.WriteLine("Argh.");
}
public MySingletonClass() {
Console.WriteLine("Making instance of My Singleton Class.");
}
}
class Demo {
public static void main() {
//MySingletonClass o0 = new MySingletonClass(); // Throws simple exception
MySingletonClass o1 = MySingletonClass.Instance;
MySingletonClass o2 = MySingletonClass.Instance;
//MySingletonClass o3 = new MySingletonClass(); // Throws simple exception
o1.scream();
o2.scream();
Console.ReadLine();
}
}
}
Any suggestions would be great.
CBAR
-- modified at 9:22 Friday 21st April, 2006
|
|
|
|
 |
|
 |
You can use a private constructor so there will be no need for a throw inside.
private Singleton(){}
http://stefanprodan.wordpress.com
|
|
|
|
 |
|
 |
declare your class as static - prevents any instantiation.
|
|
|
|
 |
|
 |
// here is it:
namespace Singleton
{
public class Get where T : new()
{
// ctor
protected Get()
{
if (Instance != null)
{
throw (new Exception("You have tried to create a new singleton class where you should have instanced it. Replace your \"new class()\" with \"class.Instance\""));
}
}
public static T Instance
{
get { return SingletonCreator.instance; }
}
class SingletonCreator
{
static SingletonCreator()
{
}
internal static readonly T instance = new T();
}
}
}
// --
namespace SingletonTest
{
class Some : Singleton.Get
{
public Some()
{
Console.WriteLine("Start!");
}
public void Test()
{
Console.WriteLine("hey!");
}
}
class Program
{
static void Main(string[] args)
{
Some.Instance.Test();
Some.Instance.Test();
Some.Instance.Test();
// we get exception here, nice!!!
Some x = new Some();
Console.ReadLine();
}
}
}
/*
we do not need locking because we use 'fully lazy instantiation',
check this at: http://www.yoda.arachsys.com/csharp/singleton.html
correct me if it's wrong, i don't know really ;}
*/
Just another style...
|
|
|
|
 |
|
 |
Any idea of how best to handle AppDomains anybody? The best I can find so far is an ipc channel to a remoted singleton object.
|
|
|
|
 |
|
 |
out of curiosity, what's the purpose of singletoncreator? from the work I've done, you don't need to have anything more than a static field to hold the instance. the runtime will keep the various instances seperate by virtue of type resolution.
|
|
|
|
 |
|
 |
If you have just a static field, if two thread access the field for the first time, at the same time, each of them will think that it hasn't been created yet and so you end up with two being created.
You can force this behaviour using the [ThreadStatic] behaviour (each thread has its own static) but the way to ensure a single instance across multiple threads is to use the Singleton Pattern.
|
|
|
|
 |
|
 |
I believe the biggest problem is the constructor of the class to be singleton is still public, meaning you could force instanciation of another object or create a new "singleton holder" for the same class, thus having more than one instance and beaking the meaning of the pattern.
If I'm wrong, please someone correct me.
[]'s
Harkos
---
"Money isn't our god, integrity will free our soul."
Cut Throat - Sepultura
|
|
|
|
 |
|
 |
If you look at the other comment and my responses, there is a solution to this using a C# 2.0 language feature which allows the constructor to be come internal (almost private) but still will allow the SingletonCreator to create the TestClass.
I have updated the article to include this, I am just waiting for it to be updated on CodeProject.
David Coleman
Footballer and Gentleman
|
|
|
|
 |
|
 |
If you have a readonly static variable created with a type initializer, it will be perfectly thread-safe, and you will not get multiple instances created.
The only reason for introducing the nested class is to enforce lazy initialization of the instance on the first access to the static property. Without the nested class, accessing any other static member would force initialization of the instance.
However, since you don't have any other static members in your class, it would be perfectly acceptable to use the fourth example from the article you refered to:
public static class SingletonProvider<T> where T:new()
{
static readonly T instance = new T();
static SingletonProvider()
{
}
public static T Instance
{
get
{
return instance;
}
}
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
|
|
|
|
 |
|
 |
What is more interesting is overall unbeliveable fascination with Singleton pattern. There is at least one 'new' implementation on Singleton on each CodeProject-like site and, during my last xy years of programming, I've came to a number of exactly zero needs of reusing someone elses singleton solution.
And, I reuse stuff. A lot.
- Goran.
|
|
|
|
 |
|
 |
I do agree Goran. The Singleton Pattern is generally overused. However, there are still instances where it is useful. This article was more about showing what generics can do for you if you think slightly differently from straightforward class templating.
David Coleman
Footballer and Gentleman
|
|
|
|
 |
|
 |
Nice article. If you've read Andrei Alexandrescu's "Modern C++ Design and Design Patterns Applied", you would have noticed that he presents a similar (but more sophisticated) solution using C++ templates.
There's one important drawback to your solution though, you can't prevent client code from directly instantiating the class (TestClass in your example), effectively bypassing the singleton mechanism. Unless you're planning on putting TestClass and SingletonProvider in a separate assembly and making TestClass' constructor internal.
C++ has the friend mechanism, which prevents the above usage, ie, the constructor is made private, but the singleton holder (SingletonProvider in your case) is declared as a friend class, so it works out okay.
And while your code is thread safe, I generally don't prefer declaring and instantiating static objects at the same time, especially if the constructor of that object does some heavy work. If the constructor throws an exception, it'll manifest itself as a TypeLoadException when somebody references the containing object, which makes tracking such things really hard.
Regards
Senthil
_____________________________
My Blog | My Articles | WinMacro
|
|
|
|
 |
|
 |
Thanks for the feedback, some very good points!
You will notice in the article that I discuss that fact that you can indeed create separate instances of TestClass as well as the Singleton. Although strictly speaking this breaks the Singleton Pattern, it does give you added flexibility of being able to choose how you use the class.
The C++ friend mechanism is neat, I wonder if there is a way of effecting the same with a mechanism in C#.
Generally speaking, a practice which I follow (which was actually recommended by several Microsoft people I have had correspondance with) is that you should try not to do any heavy work in the constructor of a class. Although there is nothing wrong with doing that, if any exceptions are thrown it is not clear or neat. Instead, I tend to use 'Initialising' methods in which the class setup is done. This may not be as appropriate if you are writing libraries for other developers to use unless documentation etc is clear so the developers know what to expect and how to use it properly. A problem with this approach however is that you need to Initalise the Singleton at start up which mean you lose any sense of lazy instantiation.
The Singleton Pattern is probably overused anyway and generally people need to examine the context of its use anyway.
Another thing to note, is that because the semantics of calling the generic Singleton Provider are quite explicit and clear, it is very unlikely that you are going to accidentaly use an instance of the TestClass when you wanted to use the Singleton.
|
|
|
|
 |
|
 |
Just found out that you can do 'friendly' assemblies in C# 2.0. There is assembly attribute 'InternalsVisibleTo'. This means you can identify the SingletonProvider in the TestClass assembly as being allowed to access the TestClass internals ... this means you can make the TestClass constructor internal.
|
|
|
|
 |
|
 |
Ok, I have three assemblies.
First assembly named library contain Singleton generic:
public class Singleton<T>
where T: new()
{
private static T instance;
public static T Instance
{
get
{
lock (typeof(T))
{
if (instance == null)
instance = new T();
return instance;
}
}
}
}
Second assembly named Entity contain some test class:
public class Entity
{
internal Entity()
{}
public void Foo()
{
Console.WriteLine("Entity.Foo()");
}
}
And third assembly contains test application:
static void Main(string[] args)
{
Singleton<Entity>.Instance.Foo(); new Entity().Foo(); }
By default neither first line, nor second line does not compile. So I add to second assembly next lines:
[assembly: InternalsVisibleTo("MainApplication")]
[assembly: InternalsVisibleTo("Library")]
Second line was compiled, but first raise compiler error: "The type 'TestEntity.Entity' must have a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Library.Singleton'".
So I have two questions:
1) Is this compiler bug or my bug?
2) If this is a compiler bug, to which assembly need to be friend to Entity assembly: Library with singleton or MainApplication?
With best regards,
Serg Matskov.
|
|
|
|
 |