Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To: Auto Instantiate Singleton in C#

Tags:

c#

singleton

I want to have a Singleton that will be auto instantiated on program start.

What I mean by "auto instantiated" is that the code in the Singleton should instantiate itself on program start without any calls or declarations by other code.

So I want something like the following to instantiate and write out "MySingleton Instantiated" on program start (without the main code doing anything)...

static class MySingleton
{
    private static MySingleton self = new MySingleton();

    protected MySingleton()
    {
        System.Console.WriteLine("MySingleton Instantiated");
    }
}

except this doesn't work since C# will only initialize the static members of a class when needed, ie when they are accessed/etc.

So what do I do? can this be done?

I haven't done this personally with C++ (haven't been using C++ for a while) but I'm pretty sure it can be done in C++ but not sure about C#.

Any help is appreciated. Thanks.


What I'm actually wanting to do with this is... There would be many of these singleton classes (and more can be added as time goes on), all of which would inherit from a common (abstract) parent class (aka. PClass).

The PClass would have a static member that is a collection of PClasses... and a constructor to add itself to the collection...

Then in theory all the singletons would automagically be added to the collection (since when they are instantiated the base PClass constructor is called and adds the new object to the collection)... then the collection can be used without knowing anything about what child (singleton) classes have been implemented, and new child (singleton) classes can be added any time without having to change any other code.

Unfortunately I can't get the children (singletons) to instantiate themselves... screwing up my little plan, resulting in this post.

Hope I explained that well enough.


PS. Yes I realize there are bad feelings around Singletons and their use... but they are useful sometimes, and even if Satan himself made Singletons I'd still like to know if my problem can be achieved in C#. Thanks kindly to you all.

like image 568
devlop Avatar asked Apr 27 '09 21:04

devlop


People also ask

How do you instantiate a singleton?

To instantiate a normal class, we use a java constructor. On the other hand, to instantiate a singleton class, we use the getInstance() method.

What is Singleton class in C?

Singleton in C++ Singleton is a creational design pattern, which ensures that only one object of its kind exists and provides a single point of access to it for any other code. Singleton has almost the same pros and cons as global variables. Although they're super-handy, they break the modularity of your code.

What is Meyers singleton?

The beauty of the Meyers Singleton in C++11 is that it's automatically thread-safe. That is guaranteed by the standard: Static variables with block scope. The Meyers Singleton is a static variable with block scope, so we are done. It's still left to rewrite the program for four threads.

Can we create instance of Singleton class in C#?

Singleton Class allow for single allocations and instances of data. It has normal methods and you can call it using an instance. To prevent multiple instances of the class, the private constructor is used.


1 Answers

The IoC approach mentioned by Chris is probably the best, but failing that the "best" solution I can think of is to do something funky with reflection and attributes along the lines of:

public class InitOnLoad : Attribute 
{ 
    public static void Initialise()
    {
        // get a list of types which are marked with the InitOnLoad attribute
        var types = 
            from t in AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes())
            where t.GetCustomAttributes(typeof(InitOnLoad), false).Count() > 0
            select t;

        // process each type to force initialise it
        foreach (var type in types)
        {
            // try to find a static field which is of the same type as the declaring class
            var field = type.GetFields(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).Where(f => f.FieldType == type).FirstOrDefault();
            // evaluate the static field if found
            if (field != null) field.GetValue(null);
        }
    }
}

[InitOnLoad]
public class Foo
{
    public static Foo x = new Foo();

    private Foo()
    {
        Console.WriteLine("Foo is automatically initialised");
    }
}

public class Bar
{
    public static Bar x = new Bar();

    private Bar()
    {
        Console.WriteLine("Bar is only initialised as required");
    }
}

With a call to InitOnLoad.Initialise() added to your main method.

You could do away with the attribute, but this may cause unnecessary types to be initialized and needlessly consume memory (such as Bar in the above code).

It's also worth noting that this won't handle types contained in any assemblies which are loaded dynamically, unless you make another call to Initialise, but based on your question ("auto instantiated on program start") that doesn't sound like an issue for you.

like image 106
Richard Avatar answered Nov 05 '22 16:11

Richard