Доступ к пользовательскому разделу конфигурации в .Net - PullRequest
7 голосов
/ 02 апреля 2009

Я пытаюсь получить доступ к настройкам в моем конфигурационном файле, который представляет собой последовательность элементов xml, перечисленных как:

<databases>
<database name="DatabaseOne" Value="[value]" />
<database name="DatabaseTwo" Value="[value]" />
</databases>

Теперь я хочу получить к нему доступ. Я настроил классы так:

Public Class DatabaseConfigurationHandler
    Inherits ConfigurationSection

    <ConfigurationProperty("Databases", IsDefaultCollection:=True)> _
   Public ReadOnly Property Databases() As DatabaseCollection
        Get
            Return CType(Me("Databases"), DatabaseCollection)
        End Get
    End Property
End Class

Public Class DatabaseCollection
    Inherits ConfigurationElementCollection

    Protected Overloads Overrides Function CreateNewElement() As ConfigurationElement
        Return (New Database())
    End Function

    Protected Overloads Overrides Function GetElementKey(ByVal element As ConfigurationElement) As Object
        Return (CType(element, Database).DatabaseName)
    End Function

End Class

Public Class Database
    Inherits ConfigurationElement

    <ConfigurationProperty("name", IsKey:=True, IsRequired:=True)> _
       Public Property DatabaseName() As String
        Get
            Return Me("name").ToString()
        End Get
        Set(ByVal Value As String)
            Me("name") = Value
        End Set
    End Property


    <ConfigurationProperty("value", IsRequired:=True)> _
Public Property DatabaseValue() As String
        Get
            Return Me("value").ToString()
        End Get
        Set(ByVal Value As String)
            Me("value") = Value
        End Set
    End Property

End Class

Я хочу иметь возможность получить элемент по его имени и вернуть значение, но я не могу этого сделать:

Dim config As New DatabaseConfigurationHandler
                config = System.Configuration.ConfigurationManager.GetSection("databases/database")
                Return config.Databases("DatabaseOne")

Мне не хватает какого-то кода, что я делаю не так? Любые другие ошибки в вышеупомянутом?

Спасибо.

Ответы [ 6 ]

7 голосов
/ 02 апреля 2009

Вот вырезка из чего-то очень похожего, что я сделал несколько дней назад.

Конфиг:

  <ListConfigurations>
    <lists>
      <add Name="blah" EndpointConfigurationName="blah" ListName="blah" ConnectionString="blah" TableName="blah" FieldsCsv="blah" DbFieldsCsv="blah"/>
      <add Name="blah2" EndpointConfigurationName="blah" ListName="blah" ConnectionString="blah" TableName="blah" FieldsCsv="blah" DbFieldsCsv="blah"/>
    </lists>
  </ListConfigurations>

Раздел конфигурации C #:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace App
{
    /// <summary>
    /// Individual list configuration
    /// </summary>
    class ListConfiguration : ConfigurationElement
    {
        [ConfigurationProperty("Name", IsKey = true, IsRequired = true)]
        public string Name
        {
            get { return (string)this["Name"]; }
        }

        [ConfigurationProperty("EndpointConfigurationName", IsRequired = true)]
        public string EndpointConfigurationName
        {
            get { return (string)this["EndpointConfigurationName"]; }
        }

        [ConfigurationProperty("ListName", IsRequired = true)]
        public string ListName
        {
            get { return (string)this["ListName"]; }
        }

        [ConfigurationProperty("ConnectionString", IsRequired = true)]
        public string ConnectionString
        {
            get { return (string)this["ConnectionString"]; }
        }

        [ConfigurationProperty("TableName", IsRequired = true)]
        public string TableName
        {
            get { return (string)this["TableName"]; }
        }

        [ConfigurationProperty("FieldsCsv", IsRequired = true)]
        public string FieldsCsv
        {
            get { return (string)this["FieldsCsv"]; }
        }

        [ConfigurationProperty("DbFieldsCsv", IsRequired = true)]
        public string DbFieldsCsv
        {
            get { return (string)this["DbFieldsCsv"]; }
        }
    }

    /// <summary>
    /// Collection of list configs
    /// </summary>
    class ListConfigurationCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new ListConfiguration();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((ListConfiguration)element).Name;
        }
    }

    /// <summary>
    /// Config section
    /// </summary>
    class ListConfigurationSection : ConfigurationSection
    {
        [ConfigurationProperty("lists")]
        public ListConfigurationCollection Lists
        {
            get { return (ListConfigurationCollection)this["lists"]; }
        }
    }
}

И код, чтобы забрать его из основного приложения:

ListConfigurationSection configSection = null;
try
{
    configSection = ConfigurationManager.GetSection("ListConfigurations") as ListConfigurationSection;
}
catch (System.Configuration.ConfigurationErrorsException)
{
}
7 голосов
/ 02 апреля 2009

Нет больше веских причин создавать подобные вещи вручную. Скорее, вы должны использовать конструктор разделов конфигурации на CodePlex:

http://csd.codeplex.com/

После установки вы можете просто добавить новый элемент в ваш проект (конструктор раздела конфигурации), а затем добавить элементы и ограничения. Я нашел его ОЧЕНЬ простым в использовании, и, вероятно, я никогда больше не напишу кусок кода для файлов конфигурации.

2 голосов
/ 02 апреля 2009

Вместо этого вы можете использовать этот обработчик конфигурации. Он будет работать для ВСЕХ пользовательских разделов конфигурации

   public class XmlConfigurator : IConfigurationSectionHandler
    {
        public object Create(object parent, 
                   object configContext, XmlNode section)
        {
            if (section == null) 
                throw new ArgumentNullException("section",
                    "Invalid or missing configuration section " + 
                    "provided to XmlConfigurator");
            XPathNavigator xNav = section.CreateNavigator();
            if (xNav == null) 
                throw new ApplicationException(
                    "Unable to create XPath Navigator"); 
            Type sectionType = Type.GetType((string)
                (xNav).Evaluate("string(@configType)"));
            XmlSerializer xs = new XmlSerializer(sectionType);
            return xs.Deserialize(new XmlNodeReader(section));
        }
    }

Ваш конфигурационный файл должен включать ссылку на тип, который представляет корневой элемент

<ConnectionConfig 
   configType="MyNamespace.ConnectionConfig, MyNamespace.AssmblyName" >

Пример файла конфигурации может выглядеть следующим образом:

<?xml version="1.0" encoding="utf-8" ?>

<ConnectionConfig 
   configType="MyNamespace.ConnectionConfig, MyNamespace.AssmblyName" >

  <ConnCompanys>
    <ConnCompany companyName="CompanyNameHere">
      <ConnApps>
        <ConnApp applicationName="Athena" vendorName="Oracle" >
          <ConnSpecs>
            <ConnSpec environments="DEV"
              serverName="Athena"
              port="1521"
              catalog="DatabaseName"
              logon="MyUserName"
              password="%%552355%8234^kNfllceHGp55X5g==" />
     <!--  etc...

И вам нужно будет определить классы, в которые отображается каждый элемент xml ... используя соответствующие атрибуты XmlSerialization ...

[XmlRoot("ConnectionConfig")]
public class ConnectionConfig
{
    private ConnCompanys comps;

    [XmlArrayItem(ElementName = "ConnCompany")]
    public ConnCompanys ConnCompanys
    {
        get { return comps; }
        set { comps = value; }
    }
    public ConnApp this[string CompanyName, string AppName]
    { get { return ConnCompanys[CompanyName][AppName]; } }

    public ConnSpec this[string CompanyName, string AppName, APPENV env]
    {
        get
        {
            return ConnCompanys[CompanyName][AppName, env];
        }
    }
}

public class ConnCompanys : List<ConnCompany>
{
    public ConnCompany this[string companyName]
    {
        get
        {
            foreach (ConnCompany comp in this)
                if (comp.CompanyName == companyName)
                    return comp;
            return null;
        }
    }
    public bool Contains(string companyName)
    {
        foreach (ConnCompany comp in this)
            if (comp.CompanyName == companyName)
                return true;
        return false;
    }
}

public class ConnCompany
{
    #region private state fields
    private string compNm;
    private ConnApps apps;
    #endregion private state fields

    #region public properties
    [XmlAttribute(DataType = "string", AttributeName = "companyName")]
    public string CompanyName
    {
        get { return compNm; }
        set { compNm = value; }
    }

    [XmlArrayItem(ElementName = "ConnApp")]
    public ConnApps ConnApps
    {
        get { return apps; }
        set { apps = value; }
    }
    #endregion public properties

    #region indexers
    public ConnApp this[string applicationName]
    { get { return ConnApps[applicationName]; } }
    public ConnSpec this[string applicationName, APPENV environment]
    {
        get
        {
            foreach (ConnSpec con in this[applicationName].ConnSpecs)
                if (con.Environment == environment)
                    return con;
            return null;
        }
    }
    #endregion indexers
}

и т.д ...

0 голосов
/ 29 октября 2009

Есть хороший простой способ сделать это, продемонстрированный и здесь:

codeproject.com / KB / XML / xml_config_section.aspx

0 голосов
/ 28 августа 2009

Возможно, вам будет интересно использовать ConfigurationElementCollection, где T - это тип дочерних ConfigurationElements. Вы можете найти образец кода в C # на http://devpinoy.org/blogs/jakelite/archive/2009/01/10/iconfigurationsectionhandler-is-dead-long-live-iconfigurationsectionhandler.aspx

Ура! * * 1004

0 голосов
/ 02 апреля 2009

Мой VB не очень жаль, но вот как вы делаете это в C #.

C #

public class AppState : IConfigurationSectionHandler
{
    static AppState()
    {
        xmlNode myConfigNode = (XmlNode)ConfigurationManager.GetSection("databases");
    }

    public object Create(object parent, object context, XmlNode configSection) {
        return configSection;
    }
}

App.Config

<configuration>
  <configSections>
    <section name="databases" type="MyAssembly.AppState, MyAssembly" />
  </configSections>
  <databases>
    <database name="DatabaseOne" Value="[value]" />
    <database name="DatabaseTwo" Value="[value]" />
  </databases>
</configuration>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...