0

This question relates to a desktop application.

Something I'm always thinking about, is a way to be able to access an object that could be considered global, like if it is declared as static. But I always avoid this.

For example, in an application a User object (or something similar) is present very often. Imagine somewhere from the business logic a data model/repository is used, and you need the user ID to pass it as a parameter to the data layer so it can load the corresponding data for the user. Most times in web applications I see that information like a user ID is coming from a URL parameter, or HTTP post data, and is sent into a controller via its action method.

In desktop applications this is different, since all 'state' stays the same. Suppose a user object is constructed once on program startup, and of course stored now in memory somewhere. How do I access it from within another part of the application? It seems there are only two options:

  1. Using a static method on a general class that contains the user object, which returns it.
  2. Injecting the user object through the whole tree of classes that need the object.

I think both options are ugly and not optimal. Since I think it's a very common situation, what are best practises to keep a good structure?

user2190492
  • 1,174
  • 2
  • 9
  • 37
  • 1
    Can you explain how is creating a static user class is misusing a static method? – Train Apr 23 '19 at 21:51
  • Because I think it's harder to mock a User object then. – user2190492 Apr 23 '19 at 22:03
  • The short answer, is use *Dependency Injection* (DI) and the *Singleton Pattern*... There are *oodles* of way to do it, and *oodles* of frameworks that do the hard work for you, good luck and happy injecting – TheGeneral Apr 23 '19 at 23:42
  • Possible duplicate of [Winforms: How to register Forms with IoC container](https://stackoverflow.com/questions/38417654/winforms-how-to-register-forms-with-ioc-container) – recnac Apr 28 '19 at 00:59

2 Answers2

0

I am not sure why you think #2 is "ugly and not optimal", but instead of injecting a User object, perhaps injecting an IUserService which has methods to obtain the current user object would be an approach to consider.

I have done similar things in various Desktop apps using Microsoft Unity, but you would have many options on various DI frameworks to consider. I'm not sure how familiar you are with DI in general, and there are loads of articles out there, but I found a decent starting point for the concept was the Microsoft patterns & practices Developer Center with some intro documentation on Unity, and of course, the most recent Unity Container Documentation on Git Hub.

Please make another post if you have a specific questions on how to implement such a pattern.

flyte
  • 1,242
  • 11
  • 18
0

I guess you are using WinForms or WPF application that you are referring to as a Desktop application. If so, you can surely utilise one of the many IoC containers to store the object(s) in a global fashion and then access it when you need it. However, I think it's not worth the effort for simple scenarios.

A simple solution would be to use a static factory, that can create an object when you need it, or store it as a static object so that it's available throughout the application, provided that its state remains the same. You can either add a generic method to return the object of type T or you can add a specific method to create the object that may require some logic.

public static class ObjectFactory
{
    public static T GetObject<T>() where T : new()
    {
        return new T();
    }

    public static User GetUserObject(param1, param2)
    {
        // some logic
        ....
        return new User();
    }
}

You can modify the above code to also store it in a dictionary if you don't need to create the object every time. Please make sure, you don't bloat the dictionary with too many objects stored in the memory, and maybe add a method to remove the object as well if you don't need it.

public static class ObjectFactory
{
    private static Dictionary<string, object> collection = new Dictionary<string, object>();

    public static T GetObject<T>() where T : new()
    {
        string key = typeof(T).ToString();

        if (collection.ContainsKey(typeof(T).ToString()))
            return (T)collection[key];

        var instance = new T();

        collection.Add(key, instance);

        return instance;
    }
}

The problem in using IoC framework for the Desktop applications is that they don't have a similar application lifetime like a web application. Once the application is started, there is no request/response like scenario. You would be showing the main form which can probably open the other form and so on.

If you are looking for a more complex solution which involves resolving forms instances along with the dependencies. Please have a look at the answer to a possible duplicate question.

I hope this helps.

Shahzad Hassan
  • 993
  • 7
  • 14