【问题标题】:How to make object accessible from anywhere, without misusing static methods?如何在不滥用静态方法的情况下从任何地方访问对象?
【发布时间】:2019-04-23 21:45:09
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 你能解释一下创建静态用户类是如何滥用静态方法的吗?
  • 因为我认为模拟用户对象更难。
  • 简短的回答是使用依赖注入(DI)和单例模式...有oodles的方法,以及大量为您完成艰苦工作的框架,祝您好运并快乐注入

标签: c# design-patterns data-structures architecture software-design


【解决方案1】:

我不确定您为什么认为 #2 “丑陋且不是最佳”,而是注入 User 对象,也许注入具有获取当前用户对象的方法的 IUserService 将是一种方法考虑。

我已经使用Microsoft Unity 在各种桌面应用程序中做过类似的事情,但是您可以在各种 DI 框架上考虑许多选项。我不确定您对 DI 的总体了解程度,并且那里有大量文章,但我发现这个概念的一个不错的起点是 Microsoft patterns & practices Developer Center 以及一些关于 Unity 的介绍文档,当然还有Git Hub 上最新的Unity Container Documentation

如果您对如何实现这种模式有任何具体问题,请再发一篇文章。

【讨论】:

    【解决方案2】:

    我猜您正在使用您所说的桌面应用程序的 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 应用程序类似的应用程序生命周期。一旦应用程序启动,就没有类似请求/响应的场景。您将显示可能可以打开其他表单的主表单,依此类推。

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

    我希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2016-09-18
      • 2021-08-05
      • 2012-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      • 2018-04-07
      • 1970-01-01
      相关资源
      最近更新 更多