tags:

views:

1665

answers:

8

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.

+5  A: 

While .NET modules can in theory (IIRC) react to module load etc, this isn't available via C#. In some frameworks (like ASP.NET) there are hooks you can use via configuration, such as hacking it via a handler or via global.asax.cs - however, for a regular C# app (console, winform etc) you would have to trigger it manually. For example, a static constructor on the class that hosts your Main entry point would get invoked.

So: what is the use-case here? When wouldn't the lazy loading approach be OK?

Marc Gravell
I edited the post to add my use-case.
devlop
+2  A: 

I doubt this is possible without doing anything from Main. Even adding a static MySingleton() {} to the class does not guarantee its instantiation if you don't use it.

Mehrdad Afshari
A: 

I don't believe that what you want is possible in .Net framework. Basically, you want something like the runtime to notify types or call some predefined static method on them that the application is loaded and running or provide a mechanism like that. Think about the overhead. The only thing the runtime ensures is to automatically call the main entry method for your program. That's it. There you can set things up and initialize them but there is nothing automatic about it. You're still explicitly hooking things up and making method calls.

Mehmet Aras
I'm starting to think it's not possible either... but it should be!I'm pretty sure it can be done in C++, although I haven't actually done it... and ya obviously C# isn't C++ but it's bothersome that this type of thing can't be done in C#.
devlop
I doubt it is even possible in C++ either. I remember there are some standard callbacks in each dll that Windows calls each time a dll is loaded, unloaded, thread attached, etc as Mark Gravell mentioned but even then you will need to explicitly initialize your singletons. Plus, in .NET, you don't have access to those callbacks. May be one possibility is to have your own bootstrapper to host .NET runtime. Then you may use the CLR hosting apis or some trick to do what you want but why? I think you should rethink your design and the necessity of this requirement.
Mehmet Aras
+1  A: 

You're basically asking the .NET framework to call some function whenever it loads an assembly. That function would be the PClass instances registrar.

There is no DllMain in C#. You can simulate this by having an assembly-level attribute and some code in your main method, which listens to whenever an assembly gets loaded. The attribute can have a "DllMain" entry point specified or point to your PCIass inheritted classes.

taoufik
+1  A: 

Tangentially, allow me to point out that this isn't really the singleton pattern as it is normally implemented. Here's the normal (simplified) implementation in C# (not including stuff like thread-safety for brevity):

public sealed class Singleton
{
static readonly Singleton _instance = new Singleton();

// private ctor
Singleton() {}

 public static Singleton Instance
 {
  get { return _instance; }
 }
}

This line from your code shouldn't even compile!

protected MySingleton()

Having said all that, I agree with the guy who inquired as to your use-case. That'd be good to know. =)

Garrett
Ya, normally people have an instance accessor like you demonstrate, but my problem is that I don't want any other code to directly access the singleton... I just want it to instantiate on its own... so no need for an accessor.Also I edited my question to add the use case explanation.
devlop
BTW, what's wrong with a protected constructor. It compiles fine.
devlop
You should get a compiler error ("Static classes cannot have instance constructors") when you add a ctor (of any access level) on a static class.
Garrett
+1  A: 

Based on what you are trying to do, I would drop the idea of a true Singleton, and use an IoC library instead.

Check out StructureMap, Castle Windsor, Ninject, and/or Autofac.

This will allow you to create class as a singleton, via the IoC library, have as many as you want, but it is just a plain old class.

Singletons have an issue in that they really mess up the testability (via unit testing) of your application.

Just do a google search on "Singleton Considered Harmful" and you will see many more references.

Alternatively, you can also use a simple Class Factory/Method factory pattern.

Chris Brandsma
I'm not familiar with the IoC libraries... and for my needs it seems more complicated than I want?Currently as a solution I basically am doing a factory method. But it's not as nice.
devlop
An IoC is not all that complicated, really. The added bonus is that an IoC can also help out the rest of your application as well because of automatic Dependency Injection. Even if you don't use it for this problem, IoC is worth looking into.
Chris Brandsma
+1  A: 

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.

Richard
Following an update to the question, it would be possible to replace the attribute with an ancestor type check. The Initialise code can then be moved to a static constructor in the base class, as soon as the base class is referenced in the application it would cause all of the ancestors to be loaded as well.
Richard
I have heard about Reflection but haven't used it... was wondering if it could be used for such a thing as this...I think this sounds like the best solution, and your follow up comment describes basically exactly what I was wanting to do. With Reflection I think this can be achieved. Thanks.
devlop
A: 

"The PClass would have a static member that is a collection of PClasses..."

Sounds like something that could be done easily with Reflection. You don't need code that runs on startup; you can just go build a list of these classes whenever you need it.

Here's an example that will load the list once when you first read the Instances property, will look in all assemblies that are loaded at that time (you could simplify this a bit if you only wanted to look in the same assembly as PClass, but your question didn't specify which assemblies you wanted to look in), and will add a single instance of any PClass descendant (but not PClass itself) to the list. Each PClass descendant will need a parameterless constructor, but you won't need any class constructors.

public class PClass
{
    private static List<PClass> m_instances;
    public static IList<PClass> Instances
    {
        get
        {
            if (m_instances == null)
                m_instances = LoadInstanceList();
            return m_instances;
        }
    }
    private static List<PClass> LoadInstanceList()
    {
        foreach (var assembly in AppDomain.GetAssemblies())
        {
            foreach (var type in assembly.GetTypes())
            {
                if (type.IsAssignableTo(typeof(PClass)) && type != typeof(PClass))
                    m_instances.Add(Activator.CreateInstance(type));
            }
        }
    }
}
Joe White
Thanks, Richard got in there first with the Reflection stuff... so giving the Check to him. But thanks for the answer anyway.You can't do multiple checks on here can you?
devlop
Activator.CreateInstance requires (by default at least) a default public constructor. The example singleton given did not provide one, this is why I used reflection to find a field of the same type as the declaring class and then get the value of that field.
Richard