GorillaApe
GorillaApe

Reputation: 3641

How to initialise a class at program startup?

 class Statistics
{
    Dictionary<decimal, Statistic> BabyDataStandardAgeHeadCircumference;
    Dictionary<decimal, Statistic> BabyDataStandardAgeLength;
    Dictionary<decimal, Statistic> BabyDataStandardAgeWeight;
    Dictionary<decimal, Statistic> BabyDataStandardWeightForLength;


}

These data are fixed - readonly and i want to load them from the database. The problem is

  1. How to make them readonly ?(i know through properties)
  2. How to fill them with data at program startup ?

Calling a method like Statistics.load() from startup event seems poor to me..

Upvotes: 0

Views: 3723

Answers (6)

code4life
code4life

Reputation: 15794

Question:

How to make them readonly ?(i know through properties)

Answer: Rather than using a Dictionary<decimal, Statistics>, think about using an immutable wrapper for the dictionary.

SO link for an implementation of an immutable Dictionary class here:

Does C# have a way of giving me an immutable Dictionary?

Question:

How to fill them with data at program startup ?

Answer: Rather than fill them with data at program startup, how about filling them at the first access to the class (static or instanced)? This would mean populating these dictionaries in the static constructor (naturally the dictionaries would have to be static members as well).

public class Statistics
{
    public static readonly ImmutableDictionary<decimal, Statistic> 
        BabyDataStandardAgeHeadCircumference;
    public static readonly ImmutableDictionary<decimal, Statistic> 
        BabyDataStandardAgeLength;
    public static readonly ImmutableDictionary<decimal, Statistic> 
        BabyDataStandardAgeWeight;
    public static readonly ImmutableDictionary<decimal, Statistic> 
        BabyDataStandardWeightForLength;

    static Statistics()
    {
        // populate the dictionaries here...
    }
}

Upvotes: 1

Steve Ellinger
Steve Ellinger

Reputation: 3973

You could make the Statistics class follow the Singleton Pattern; and in the Instance property get create an instance if one is not already created:

class Statistics
{
    private static Statistics sInstance;
    private static Object sInstanceLock = new Object();
    private Statistics() {
        // Load data from database here...
    }
    public static Statistics Instance {
        get {
            lock(sInstanceLock) {
                if(sInstance == null) {
                    sInstance = new Statistics();
                }
                return sInstance;
            }
        }
    }
}

This would mean initialization would not necessarily have to take place at startup, although you could by invoking the Instance property at startup.

As for the read-only aspects I am not sure what your requirements are. If you mean that no one would be able to change the dictionary (add an element, remove an element) you could look at the answer to the question here: Immutable Dictionary. If you mean that no one can change the object that is stored as the value at a particular entry in the dictionary, then you would have to make the class or value type that is stored there immutable, the String class in .Net is an example of this.

Upvotes: 0

Michael
Michael

Reputation: 3831

Actually, the properties you listed are collections based on the Dictionary class. The management (Add(), Remove(), [] indexer) of objects in a Dictionary is accessible by any instance that can see the BabyData... objects. In other words, you cannot make them read-only because the Dictionary class does not support that mode of operation via properties. You would have to declare the Dictionary as private and then interface each one via methods. This is the "dirty" approach.

OR, you can create a class based on the Dictionary class that controls the addition of objects via overloading. This is more complicated, but more in tune with what you are needing (from what I can understand).

As far as loading from the database, you'd need to tell us how you are able to fetch data from the database (via Sql, Linq to Sql, DataSet table adapters, etc.) to determine what is the best method for fetching the data into your Dictionary collections.

Upvotes: 0

quentin-starin
quentin-starin

Reputation: 26698

Make a class that can create, load, and return your Statistics class, I would expose the method that does so through an interface:

public interface IStatisticsRepository {
    Statistics GetStatistics();
}

public class StatisticsRepository : IStatisticsRepository {

    private Statistics _statistics = null;

    private void LoadStatistics() {
         _statistics = GetFromDBHere();
    }

    public Statistics GetStatistics() {
        if (_statistics == null) {
            LoadStatistics();
        }

        return _statistics;

}

Then, your implementation of that interface is a service that can be used wherever. I'd inject it anywhere you need to get your statistics.

Upvotes: 0

Kirk Woll
Kirk Woll

Reputation: 77616

If you make them readonly or use properties, the dictionaries themselves will still be modifiable. One option is to make them private and provide GetXXX methods to retrieve the values.

class Statistics
{
    private static Dictionary<decimal, Statistic> babyDataStandardAgeHeadCircumference;
    private static Dictionary<decimal, Statistic> babyDataStandardAgeLength;
    private static Dictionary<decimal, Statistic> babyDataStandardAgeWeight;
    private static Dictionary<decimal, Statistic> babyDataStandardWeightForLength;

    static Statistics() 
    {
        // Put code to load from database here.  Will get called *once* when 
        // the *class* is first initialized.
    }

    public Statistic GetBabyDataStandardAgeHeadCircumfrence(decimal val) 
    {
        return babyDataStandardAgeHeadCircumfrence[val];
    }

    ...
}

Upvotes: 4

Ondrej Tucny
Ondrej Tucny

Reputation: 27974

Making it read-only: make yourself a wrapper class implementing IDictionary in a read-only manner.

Initializing upon application start-up:

  • If you do need precise order of initialization operations, the Statistics.Load() approach isn't anything odd. Also, this gives you a reasonable room for error handling in case of database connection failures.
  • If you don't have to care of order of initialization, use a static constructor. By following this approach you'll have to make sure the database is accessible (in other words, there won't be any legitimate error situations) and that the first use of the class (which actually triggers the static constructor) isn't “too soon”.

Upvotes: 1

Related Questions