2014-01-16 144 views
11

我有一個執行FTP操作的c#.Net控制檯應用程序。 目前,我在自定義配置部分中指定了設置,例如閱讀外部配置文件

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <configSections> 
    <section name="ftpConfiguration" type="FileTransferHelper.FtpLibrary.FtpConfigurationSection, FileTransferHelper.FtpLibrary" /> 
    </configSections> 

    <ftpConfiguration> 
     <Environment name="QA"> 
     <sourceServer hostname="QA_hostname" 
         username="QA_username" 
         password="QA_password" 
         port="21" 
         remoteDirectory ="QA_remoteDirectory" /> 
     <targetServer downloadDirectory ="QA_downloadDirectory" /> 

     </Environment> 
    </ftpConfiguration> 

</configuration> 

我想在命令行中指定一個外部配置文件。

無論其!!! ...

我才意識到是上述「FtpConfiguration」部分沒有真正在應用程序的App.config中的歸屬。我的最終目標是,我有我的執行控制檯應用程序,很多這樣的計劃任務:

FileTransferHelper.exe -c FtpApplication1.config 
FileTransferHelper.exe -c FtpApplication2.config 
... 
FileTransferHelper.exe -c FtpApplication99.config 

因此,我相信我已經錯了路而我真正想要的東西在我的自定義閱讀xml文檔,但繼續使用System.Configuration來獲取值...而不是讀取XmlDocument並將其序列化以獲取節點/元素/屬性。 (雖然我不反對後者,如果有人可以給我看一些簡單的代碼)

指針將不勝感激。謝謝。

更新: 我接受的是另一個問題StackOverflow上的鏈接的答案,我的代碼在這裏重複 - 低於正是我一直在尋找的是 - 使用OpenMappedExeConfiguration打開我的外部配置文件

ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap(); 
configFileMap.ExeConfigFilename = @"D:\Development\FileTransferHelper\Configuration\SampleInterface.config"; 

Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None); 

FtpConfigurationSection ftpConfig = (FtpConfigurationSection)config.GetSection("ftpConfiguration"); 
+1

正如注意,如果你決定只解析XML:XmlDocument的是在C#中處理XML的老路上,而你肯定能做到這一點,我建議使用的XDocument ,pa Linq-to-Xml的rt。 – Magus

回答

11

如果你想使用System.Configuration來打開你的自定義文件,你可能想檢查這個帖子:Loading custom configuration files。奧利弗以一種非常直接的方式指出它。

由於您想讀取通過命令行傳遞給應用程序的參數,因此您可能需要訪問此MSDN帖子:Command Line Parameters Tutorial

如果您想使用自定義方法,可以通過幾種方法來完成此操作。一種可能性是實現一個加載器類,並使用您的自定義配置文件。

例如,假設一個簡單的配置文件看起來像這樣:

spec1.config

<?xml version="1.0" encoding="utf-8"?> 
<Settings> 
    <add key="hostname" value="QA_hostname" /> 
    <add key="username" value="QA_username" /> 
</Settings> 

一個非常簡單的,哈希表樣(鍵值對)結構。

的實現,那麼解析器/讀者會是這個樣子:

 private Hashtable getSettings(string path) 
     { 
      Hashtable _ret = new Hashtable(); 
      if (File.Exists(path)) 
      { 
       StreamReader reader = new StreamReader 
       (
        new FileStream(
         path, 
         FileMode.Open, 
         FileAccess.Read, 
         FileShare.Read) 
       ); 
       XmlDocument doc = new XmlDocument(); 
       string xmlIn = reader.ReadToEnd(); 
       reader.Close(); 
       doc.LoadXml(xmlIn); 
       foreach (XmlNode child in doc.ChildNodes) 
        if (child.Name.Equals("Settings")) 
         foreach (XmlNode node in child.ChildNodes) 
          if (node.Name.Equals("add")) 
           _ret.Add 
           (
            node.Attributes["key"].Value, 
            node.Attributes["value"].Value 
           ); 
      } 
      return (_ret); 
     } 

同時,你仍然可以使用ConfigurationManager.AppSettings[]從原來的app.config文件中讀取。

5

我的首選解決方案使用XDocument。我沒有測試過,所以可能會有一些小問題,但這是爲了證明我的觀點。

public Dictionary<string, string> GetSettings(string path) 
{ 

    var document = XDocument.Load(path); 

    var root = document.Root; 
    var results = 
    root 
     .Elements() 
     .ToDictionary(element => element.Name.ToString(), element => element.Value); 

    return results; 

} 

將返回包含元素的名稱和值的字典從形式的XML:

<?xml version="1.0" encoding="utf-8"?> 
<root> 
    <hostname>QA_hostname</hostname> 
    <username>QA_username</username> 
</root> 

我覺得這是很好的解決方案,因爲它的整體簡潔。

再說一遍,我不指望它完全按照原樣工作。使用XAttributes和XElements等,你絕對可以使它更像你的原創。這將很容易過濾。

+0

+1,我喜歡它的緊湊程度。 – OnoSendai

+0

@OnoSendai:這確實是Linq最喜歡的部分之一,我不認爲很多人意識到它甚至在那裏。我想,這是比較新的。雖然名稱空間的工作方式可能有點混亂。 – Magus

12

如果你走下自定義路徑,我會誠實地使用JSON來存儲配置,然後反序列化來加載它並序列化來編寫它。 Json.NET可以讓你輕鬆做到這一點。

你的XML:

<ftpConfiguration> 
    <Environment name="QA"> 
    <sourceServer hostname="QA_hostname" 
        username="QA_username" 
        password="QA_password" 
        port="21" 
        remoteDirectory ="QA_remoteDirectory" /> 
    <targetServer downloadDirectory ="QA_downloadDirectory" /> 

    </Environment> 
</ftpConfiguration> 

看起來像這樣JSON:

{ 
    "FtpConfiguration": { 
    "Environment": { 
     "Name": "QA", 
     "SourceServer": { 
     "HostName": "QA_hostname", 
     "UserName": "QA_username", 
     "Password": "QA_password", 
     "Port": "21", 
     "RemoteDirectory": "QA_remoteDirectory" 
     }, 
     "TargetServer": { 
     "DownloadDirectory": "QA_downloadDirectory" 
     } 
    } 
    } 
} 

你的類會是什麼樣子:

class Config 
{ 
    public FtpConfiguration FtpConfiguration { get; set; } 
} 

class FtpConfiguration 
{ 
    public Environment Environment { get; set; } 
} 

class Environment 
{ 
    public SourceServer SourceServer { get; set; } 
    public TargetServer TargetServer { get; set; } 
} 

class SourceServer 
{ 
    public string HostName { get; set; } 
    public string UserName { get; set; } 
    public string Password { get; set; } 
    public int Port { get; set; } 
    public string RemoteDirectory { get; set; } 
} 

class TargetServer 
{ 
    public string DownloadDirectory { get; set; } 
} 

你會保存設置成類似於對象這個:

var config = new Config() 
{ 
    FtpConfiguration = new FtpConfiguration() 
    { 
     Environment = new Environment() 
     { 
      SourceServer = new SourceServer() 
      { 
       HostName = "localhost", 
       UserName = "jaxrtech", 
       Password = "stackoverflowiscool", 
       Port = 9090, 
       RemoteDirectory = "/data", 
      }, 
      TargetServer = new TargetServer() 
      { 
       DownloadDirectory = "/downloads" 
      } 
     } 
    } 
}; 

然後,您可以像這樣的文件(或使用Stream如果一個更大的文件):

string json = JsonConvert.SerializeObject(config); 
File.WriteAllText("config.json", json); 

然後,您可以像這樣的文件(同樣可以使用在讀Stream代替):

string json = File.ReadAllText("config.json"); 
Config config = JsonConvert.DeserializeObject<Config>(json);