首页 > 解决方案 > 如何在不滥用静态方法的情况下从任何地方访问对象?

问题描述

这个问题与桌面应用程序有关。

我一直在考虑的事情是一种能够访问可以被认为是全局的对象的方法,就像它被声明为静态一样。但我总是避免这种情况。

例如,在应用程序中,用户对象(或类似的东西)经常出现。想象一下,在业务逻辑的某个地方使用了数据模型/存储库,您需要用户 ID 将其作为参数传递给数据层,以便它可以为用户加载相应的数据。大多数时候,在 Web 应用程序中,我看到诸如用户 ID 之类的信息来自 URL 参数或 HTTP 发布数据,并通过其操作方法发送到控制器。

在桌面应用程序中这是不同的,因为所有“状态”都保持不变。假设一个用户对象在程序启动时被构建一次,当然现在存储在内存中的某个地方。如何从应用程序的另一部分访问它?似乎只有两种选择:

  1. 在包含用户对象的通用类上使用静态方法,该对象返回它。
  2. 通过需要该对象的整个类树注入用户对象。

我认为这两种选择都很丑陋而且不是最优的。既然我认为这是一种非常普遍的情况,那么保持良好结构的最佳做法是什么?

标签: c#design-patternsdata-structuresarchitecturesoftware-design

解决方案


我猜您正在使用您称为桌面应用程序的 WinForms 或 WPF 应用程序。如果是这样,您当然可以利用众多 IoC 容器之一以全局方式存储对象,然后在需要时访问它。但是,我认为对于简单的场景不值得付出努力。

一个简单的解决方案是使用静态工厂,它可以在需要时创建对象,或者将其存储为静态对象,以便在整个应用程序中可用,前提是其状态保持不变。您可以添加通用方法来返回类型对象,T也可以添加特定方法来创建可能需要一些逻辑的对象。

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();
    }
}

如果您不需要每次都创建对象,则可以修改上述代码以将其也存储在字典中。请确保,您不会因为存储在内存中的太多对象而使字典膨胀,并且如果您不需要它,也可以添加一个删除对象的方法。

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;
    }
}

将 IoC 框架用于桌面应用程序的问题在于,它们没有与 Web 应用程序类似的应用程序生命周期。一旦应用程序启动,就没有类似请求/响应的场景。您将显示可能可以打开其他表单的主表单,依此类推。

如果您正在寻找更复杂的解决方案,其中涉及解析表单实例以及依赖项。请查看可能重复问题的答案。

我希望这有帮助。


推荐阅读