【问题标题】:Share config between UI and service在 UI 和服务之间共享配置
【发布时间】:2015-09-03 01:17:05
【问题描述】:

有没有办法在不同的程序集中反序列化user.config?我需要一个绑定到Properties.Settings 的表单,然后是一个访问这些设置的服务。

我试过ConfigurationManager 可以很好地加载配置,但似乎有某种保护措施使userSettings 部分无法触及。

到目前为止失败的另一件事是XmlSerializer,我不确定它是否可以映射到配置文件结构。

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    我使用过类似使用内置 XmlTextReader 读取 user.config 文件的方法。

    但我还要说,使用文本文件将您的服务和 UI 耦合起来似乎是一个糟糕的设计,尤其是用户配置文件,考虑到该文件很容易被意外值填充(例如,用户可能输入错误错误的值,然后关闭 UI,将错误的值留在配置文件中)。

    如果你能告诉我更多关于你的应用程序的信息,我可以推荐一个更好的方法。

              XmlTextReader reader = new XmlTextReader(filename);
                {
                    while (reader.Read())
                    {
                        switch (reader.NodeType)
                        {
                            case XmlNodeType.Text:
                                switch (settingKey) //Do something
                                {
    

    更新:

    您的方法的问题在于它违反了“关注点分离”的原则,因为更改您的 UI 将更改您的模型(在 UI 应用程序上),这将与您的服务上的模型不同步。这是 user.config 的工作方式,因为它通常不用于存储应用程序之间共享的数据(这就是通常使用配置文件的方式),因此它在幕后发挥了一些魔力,使其易于设置。

    这就是我的做法。

    假设您有一个名为 Employee 的模型: (借用here的代码)

    [XmlRoot("employee")]
    public class EmployeesModel
    {
        [Required]
        [DisplayName("Name: ")]
        [XmlElement("employeeName")]
        public string employeeName { get; set; }
    
        [Required]
        [DisplayName("Position: ")]
        [XmlElement("employeePosition")]
        public string employeePosition { get; set; }
    
        //etc
    }
    

    您可以使用以下方式将您的 XML 反序列化为该模型的新实例:

    var serializer = new XmlSerializer(typeof(EmployeesModel));
    employee anEmployee = 
        from xml in xmlDoc.Descendants("employee")
        select serializer.Deserialize(xml.CreateReader()) as EmployeesModel;
    

    现在在您的服务中,您可以使用 XML 中的 EmployeesModel 实例。

    在您的 GUI 中,您可以非常小心地使用与模型相同的字段名称,以便您的 user.config XML 与您的模型匹配。例如。如果您在 GUI 中更改“employeeName”文本框,那么您的 GUI 仍然可以正常工作,但它会将控件序列化为新名称,然后会中断您的服务。

    它避免了这种紧密耦合,在这种情况下您可以轻松破坏事物,我会将您的员工姓名文本框直接绑定到模型,执行类似 this using INotifyPropertyChanged 的操作。数据绑定非常复杂,因此您可能需要阅读它here

    这就是为什么您不能在弄乱 UI 时无意中更改模型的原因,因为 UI 将不再正确绑定并且您会收到编译错误。

    然后您仍然需要序列化您的控件(例如,当您的 UI 关闭时),但这很容易,因为这些文本框和其他控件已绑定到模型。所以你所要做的就是:

       XmlSerializer xmlserializer = new XmlSerializer(EmployeesModel);
        StringWriter stringWriter = new StringWriter();
        XmlWriter writer = XmlWriter.Create(stringWriter);
    
        xmlserializer.Serialize(writer, anEmployee); //this is your model instance from above
    
        serializeXml = stringWriter.ToString();
    
        writer.Close();
    

    希望对你有帮助。

    【讨论】:

    • UI 验证输入。我目前正在使用我可以序列化/反序列化的设置类。内置设置的优点是它们可以轻松绑定到控件,使用存储的值自动填充它们,可以检查是否同步等。我当然希望避免将设置读取为 xml。
    • 但是如果您的服务没有任何控件,您就会遇到这种不平衡,即控件绑定到文本文件,然后您的文本文件必须绑定到服务中的某些自定义类型。在我看来,最好为文本文件创建 1 个接口,然后将您的控件或其他类型绑定到该接口。如果有帮助,我可以更新我的答案以解释更多。我看不出如何避免使用 XML - 配置文件是 XML。
    • 我不想避免将 xml 作为序列化格式,我想避免将其读取为 xml。我不确定您将控件绑定到界面是什么意思,只是为了澄清一下,该服务是一个没有任何界面的无头进程。
    • 感谢您为我指明正确的方向。幸运的是,即使没有实现 INotifyPropertyChanged,自定义数据绑定也很有用,这使得它在生产力方面也可以与内置设置竞争。
    • 我希望写出这个答案是为了帮助读者思考设计原则,而不是仅仅依靠幕后的魔法。如果您确实想出了一个运行良好的代码 sn-p,请将其发布给未来的读者。
    猜你喜欢
    • 1970-01-01
    • 2020-02-06
    • 1970-01-01
    • 2020-05-05
    • 2010-12-26
    • 1970-01-01
    • 2011-11-12
    • 2023-04-10
    • 2016-07-31
    相关资源
    最近更新 更多