在应用程序启动期间从文件加载值的正确方法是什么?

时间:2014-02-24 12:23:51

标签: c# xml

我已将某些值存储在xml文件中。这些值将在应用程序启动时读取,并且应该可用于所有其他类。 xml的结构如下:

<Values>
    <Tag1>Value1</Tag1>
    <Tag2>Value2</Tag2>
    <Tag3>Value3</Tag3>
</Value>

它们应该只读一次,并且在启动时也是如此。如果在应用程序启动并读取了所有值后,通过某种方式更改值,则不应影响应用程序已读取的值。我的意思是说它不应该像每当一个类对象在运行时需要一个值时,每次读取xml并重新获取值。

我的第一个问题是: 这是一个好习惯吗?

如果是,那么,

在C#中执行此操作的最佳方法是什么?

我发现一个包含所有值的静态成员的静态类和一个将值写入这些成员的静态方法将解决这个问题。

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        string strPath = "";
        XmlDocument doc = new XmlDocument();
        doc.Load(strPath);
        Reader.ReadXml(doc.SelectSingleNode("/Values/Tag1").InnerText,doc.SelectSingleNode("/Values/Tag2").InnerText,doc.SelectSingleNode("/Values/Tag3").InnerText);
        Application.Run(new class1());
    }
}

public static class Reader
{
    public static string str1;
    public static string str2;
    public static string str3;

    private static void ReadXml(string s1, string s2, string s3)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(strXmlPath);
        str1 = s1;
        str2 = s2;
        str3 = s3;
    }
}

class xyz
{        
    string GetValue()
    {
        return Reader.str1;
    }
}

这是我尝试过的。这是处理这种情况的正确方法吗?请告诉我这种情况下的正确方法。

此外,如果值的数量多于那么,我应该传递那么多变量吗?

3 个答案:

答案 0 :(得分:2)

是的,很好,但是如果这个值是应用程序配置,您可以将它放在web.config文件中并使用ConfigurationManager来获取此值。 (您也可以使用配置文件中的部分。)

例如:

<appSettings>
<add key="nameKey1" value="Value1"/>
<add key="nameKey2" value="Value2"/>
<add key="nameKey3" value="Value3"/>
</appSettings>

并称之为:

string key1 = System.Configuration.ConfigurationManager.AppSettings["nameKey1"];

我希望我有所帮助

(对不起我的英文)

答案 1 :(得分:0)

你所做的安排并没有什么问题,但我会改变一些事情 - 大部分是隐藏程序获取数据的细节。

我会将读取器对象和应用程序设置数据分开 - 随着应用程序的增长,它们往往会有越来越多的设置,因此用于读取和存储数据的代码往往会增长。您可能 - 在将来 - 想要一些其他数据源(数据库,网络服务等)而不是和XML文件。如果将设置阅读器和设置数据绑在一起,则更难进行这些更改。

首先,我创建一个界面来定义设置阅读器:

public interface ISettingReader
{
    int ReadSomeAppInt ();

    // TODO add other read functions
}

然后,您可以通过多种方式实现此界面:

public class XmlAppSettingReader : ISettingReader
{
    public XmlAppSettingReader ( string sFilename )
    {
        // TODO open XML file and get ready to read settings
    }

    public int ReadSomeAppInt ()
    {
        // TODO read the named integer from XML and return it
    }
}

如有必要,您还可以为数据库等实现此功能

然后我会创建某种静态设置类(例如,GlobalSettings等)除了存储和返回应用程序范围的设置值之外什么都不做。这个类还有一个Init函数,用于在指定设置读取器的pplication启动时初始化其值。

public static class GlobalSettings
{
    // TODO add public static get properties for various settings
    private static int s_nSomeAppInt;

    public static void Init ( ISettingReader oReader )
    {
        // TODO use reader to read individual setting values

        int nSomeAppInt = oReader.ReadSomeAppInt ();

        // TODO validate nSomeAppInt and store it in private
        // static field
        s_nSomeAppInt = nSomeAppInt;
    }

    public static int SomeAppInt
    {
        get
        {
            return ( s_nSomeAppInt );
        }
    }
}

然后,您可以在Main功能中加载设置:

{
    ISettingReader oReader = new XmlAppSettingReader ( "C:\file.xml" );
    GlobalSettings.Init ( oReader );

    // TODO continue startup
}

此设置允许您处理加载应用程序设置并将它们彼此独立地提供给内部组件。您可以轻松更改,而不会轻易影响另一方。

为了进一步细化(如Jon Skeet评论),使GlobalSettings非静态并实现其自己的IGlobalSettings接口。然后,每个应用程序组件将从该对象接收IGlobalSettings引用和读取设置,而不是尝试访问全局静态对象。

答案 2 :(得分:0)

如果您的xml采用如下所示的序列化格式:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfValues xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Values>
        <Tag1>Value1</Tag1>
        <Tag2>Value2</Tag2>
        <Tag3>Value3</Tag3>
    </Values>
</ArrayOfValues>

你有一个类要反序列化,如下所示:

public class Values
{
    // set the types accordingly
    public string Tag1 { get; set; }
    public string Tag2 { get; set; }
    public string Tag3 { get; set; }
}

此外,您可能有一个包含反序列化代码的类:

using System.Xml.Serialization;

namespace Serialization
{
    public class ValuesGenerator
    {
        private const string XmlPath = "SPECIFY THE XML FULL PATH HERE";

        public List<Values> GetColumnInfo()
        {
            var serializer = new XmlSerializer(typeof(List<Values>));
            return (List<Values>)serializer.Deserialize(new StreamReader(XmlPath));
        }
    }
}

然后你可以在你的程序开头反序列化它,如下所示:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        // look for the following 2 lines
        var valuesGenerator = new ValuesGenerator();
        List<Values> values = valuesGenerator.GetColumnInfo(); // This is the list which contains the deserialized info

        Application.Run(new class1());
    }
}