-2

Is there some kind of trick, or design pattern, or some other way universal ways to make an object available 'globally', so you can access an object as needed from an application so it can be loaded with the loading process of the application (regardless of if it is a desktop app such as console, or a web app such as MVC)

I am basically looking for something that I can initialize in the main starting method and it will be available without having to pass it to each method to use it, while it retains its state and properties that it was initialized with.

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
CodingRiot
  • 197
  • 1
  • 4
  • 16
  • Sure, define `public static class Globals { public static object EvilGlobal {get; set;} }` and then you can access `Globals.EvilGlobal` from anywhere. – Blorgbeard Jan 11 '17 at 19:22
  • I believe you're looking to make an object static: https://msdn.microsoft.com/en-us/library/98f28cdx.aspx – Timothy Stepanski Jan 11 '17 at 19:22
  • 1
    There are various options depending on the type of app (web/console/whatever) but this is almost always an antipattern. – DavidG Jan 11 '17 at 19:23
  • Suppose you had this but when you tried to use it, [it was corrupt](https://en.wikipedia.org/wiki/God_object). How are you going to find what corrupted it? It could be anything. Instead, create [immutable](http://stackoverflow.com/questions/622664/) objects and pass them only to objects that [need to know](https://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)) the object. – Dour High Arch Jan 11 '17 at 19:27
  • Note that making objects available *across process boundaries* is highly non-trivial (and also an even worse idea than a simple singleton) – BradleyDotNET Jan 11 '17 at 19:31
  • no trick .. you can save them in a shared resource like database or XML/JSON/INI etc. file. – Slai Jan 11 '17 at 19:35
  • 3
    This is an [XY Problem, you think that this global access object will fix a problem you have, buy you haven't actually described the real problem, only your attempted fix for it](http://meta.stackexchange.com/a/66378/171858). – Erik Philips Jan 11 '17 at 19:44

2 Answers2

3

As I mentioned in my comment, this looks like an XY Problem. Instead of actually doing global variables, which most people on stack overflow feel are a no-no, I believe the correct solution is to just use IoC/DI. I prefer to use Autofac(no affiliation and there are plenty of DI frameworks to choose from). This allows each object to simply request (by constructor injection or the not recommended approach of property injection) the objects it needs to use in order to function properly. This decreases coupling and can help with testing code (unit tests).

using System;
using Autofac;

public class Program
{
    public static void Main()
    {
        // Start configuring DI
        IoCConfig.Start();

        // Start "scope" in which Autofac builds objects "in"
        using(var scope = IoCConfig.Container.BeginLifetimeScope())
        {
            // Resolve the Worker
            // Autofac takes care of the constructing of the object
            // and it's required parameters
            var worker = scope.Resolve<Worker>();

            worker.DoWork();
        }
    }
}

// the class that does work, it needs the Configuration information
// so it is added to the constructor parameters
public class Worker
{
    private readonly string _connectionString;

    public Worker(IConfiguration config)
    {
        _connectionString = config.ConnectionString;
    }

    public void DoWork()
    {
        // Connect to DB and do stuff
        Console.WriteLine(_connectionString);
    }
}

public static class IoCConfig
{
    public static IContainer Container { get; private set; }

    public static void Start()
    {
        var builder = new ContainerBuilder();


        // Register Global Configuration
        builder.Register(c => new Configuration{
            ConnectionString = "my connection string" // or ConfigurationManager.ConnnectionString["MyDb"].ConnectionString;
        })
            .As<IConfiguration>();

        // Register an concrete type for autofac to instantiate
        builder.RegisterType<Worker>();

        Container = builder.Build();
    }

    private class Configuration : IConfiguration
    {
        public string ConnectionString { get; set; }
    }

}

public interface IConfiguration
{
    string ConnectionString { get; }
}
Community
  • 1
  • 1
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
1

I think you are looking for the Singleton Pattern

https://msdn.microsoft.com/en-us/library/ff650316.aspx

enno.void
  • 6,242
  • 4
  • 25
  • 42
  • 2
    While this may be a quick-and-dirty fix, the question mentions using it to maintain state. When the Singleton Pattern is used for storing state, all you're really getting is a global variable in disguise. This is a lot more like an anti-pattern than something to recommend. – Ben Cottrell Jan 11 '17 at 20:10