【问题标题】:Storing global immutable data in static classes在静态类中存储全局不可变数据
【发布时间】:2011-11-22 14:20:25
【问题描述】:

我有一个 WinForms 项目,它使用了很多用户控件。其中一些用户控件使用来自业务逻辑层的类。这些类主要对数据库执行 CRUD 操作(通过数据访问层)以及一些额外的验证和报告。

该项目使用了一些常见的对象(登录用户、一些控制器和验证器),这些对象在主窗体中被实例化,然后通过初始化方法或公共属性注入到子用户控件中。这意味着,我有很多代码,只是将这些公共对象从父控件传递到子控件。

为了避免这种情况,我可以创建一个静态类(例如 ApplicationContext)并将所有常用控件保存到其中。这将发生在主窗体中,项目中的所有其他用户控件或窗体都可以使用它。

我发现通常不鼓励这种模式(将一些全局数据存储在静态类中)。但是如果这些数据是不可变的呢?这种方法是个好主意吗?

或者你知道任何其他方法可以帮助我摆脱所有初始化代码吗?

【问题讨论】:

    标签: c# .net static global application-design


    【解决方案1】:

    您可以使用Inversion of Control 容器,例如UnityAutofac,并让它自动为您连接您的对象图。

    您可以让需要任何一个公共对象的每个对象定义对其接口的依赖关系,无论是通过构造函数参数还是作为公共属性,IoC 容器会将适当的对象连接在一起。

    Unity 的属性注入示例:

    public class MyUserControl : UserControl 
    {
        [Dependency]
        public LoggedUserService UserService { get; set; }
    
        public void Method()
        {
            // the IoC container will ensure that the UserService
            // property has been set to an object
        }
    }
    

    您在主窗体中所做的只是注册您希望 IoC 容器了解的公共对象,然后请求根对象。对象图会为您神奇地组装起来,您不必了解所有的线代码,也不必关心它是如何完成的。

    【讨论】:

    • IoC 容器正是我想要的,谢谢。我选择了ninject :)
    【解决方案2】:

    您可以使用静态类来存储一些不可变数据——这没问题。 但是,如果您想在那里存储控件,它可能无法按预期工作。 例如 OnDataBinding 和 Render 等方法。

    【讨论】:

      【解决方案3】:

      您可以使用依赖注入/ioc 容器来维护您的全局对象。 我对autofac library 有很好的体验,但还有很多其他可用的。 使用 setter 注入时,您的所有控件都会自动设置依赖对象。

      【讨论】:

        【解决方案4】:

        在这种情况下,您需要使用单例。单例将允许您使用对象的相同实例,比静态更安全和灵活。

        public sealed class Singleton
        {
            public object Property1 {get;set;}
            public void Method1 (){}
        
            static Singleton instance = null;
            static readonly object padlock = new object();
        
            Singleton()
            {
            }
        
            public static Singleton Instance
            {
                get
                {
                    lock (padlock)
                    {
                        if (instance==null)
                        {
                            instance = new Singleton();
                        }
                        return instance;
                    }
                }
            }        
        }
        

        然后你可以像使用静态一样使用它,但有点不同......

        public class Main
        {
             public Main()
             {
                 Singleton.Instance.Property1 = "somevalue";
                 Singleton.Instance.Method1();
             }
        
        }
        

        【讨论】:

        • 如果单例不是不可变的,则它们是不好的。可以随时更改的全局状态是难以解决的错误来源。
        • 你是对的,如果他正在更改对象而不是仅仅访问它们。但是,我知道他是在 Main 中设置它们,为了避免传递这些未更改的实例,他可以使用 Singleton。
        猜你喜欢
        • 1970-01-01
        • 2011-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-20
        • 2016-03-31
        • 1970-01-01
        • 2021-07-25
        相关资源
        最近更新 更多