用.NET 2.0 Enterprise Library库读写App.config文件(3)

Enterprise Library Configuration Helpers

The Enterprise Library for .NET 2.0 has made it a lot easier to use the System.Configuration classes.More info how to configure the new application blocks you can  be found in another article. Lets suppose you want to store a collection of strongly typed named objects in our App.Config file. In this example it is a plugin configuration file where a list of plugins can be added and the selected plugin be started. The config file could look like this:

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

<configuration>

  <configSections>

    <section name="PluginConfiguration" type="EntlibInjection.PluginManagerConfiguration, EntlibInjection, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />

  </configSections>

 

  <PluginConfiguration name="Configured Plugins" SelectedPlugin="2D">

    <Plugins>

      <!-- type="EntlibInjection.PluginData, EntlibInjection, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" -->

      <add name="2D" cfgfile="2D.config" plugintype="EntlibInjection.TwoD, EntlibInjection, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" type=""/>

      <add name="3D" plugintype="ThreeDPlugin.ThreeD, ThreeDPlugin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" type=""/>

    </Plugins>

  </PluginConfiguration>

 

</configuration>


We want a PluginConfiguration class which selects a plugin and contains a list of plugins. To make it work we first need to define the PluginManagerConfiguration class. We need the Enterprise Library  only for the 
IConfigurationSource interface to load our config from other files than App.config or even an SQL server.

PluginManagerConfiguration.cs

using System;

using System.Configuration;

using System.ComponentModel;

using System.Collections.Generic;

using System.Text;

using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

 

namespace EntlibInjection

{

    public class PluginManagerConfiguration : SerializableConfigurationSection

    {

            private const string selectedPlugin = "SelectedPlugin";

            private const string PluginCollectionProperty = "Plugins";

            private const string nameProperty = "name";

 

 

            /// <summary>

            /// Configuration section name for Plugin Configuration

            /// </summary>

            public const string SectionName = "PluginConfiguration";

 

 

            public PluginManagerConfiguration()

            {

 

            }

 

            /// <summary>

            /// Gets the configured plugin settings section in the configuration source.

            /// </summary>

            /// <param >The <see cref="IConfigurationSource"/> to get the section from.</param>

            /// <returns>The plugin configuration.</returns>

            public static PluginManagerConfiguration GetPluginSettings(IConfigurationSource configurationSource)

            {

               return (PluginManagerConfiguration)configurationSource.GetSection(PluginManagerConfiguration.SectionName);

            }

 

            /// <summary>

            /// Get/Set the selected plugin

            /// </summary>

           [ConfigurationProperty(selectedPlugin, IsRequired = true)]

            public string SelectedPlugin

            {

                  get

                  {

                     return (string)this[selectedPlugin];

                  }

                  set

                  {

                     this[selectedPlugin] = value;

                  }

            }

 

        /// <summary>

        /// Name of the configuration node.

        /// </summary>

        [ConfigurationProperty(nameProperty)]

        [EditorBrowsable(EditorBrowsableState.Never)]

        public string Name

        {

            get

            {

                return (string)this[nameProperty];

            }

            set

            {

                this[nameProperty] = value;

            }

        }

 

            /// <summary>

            /// This property contains a list of plugins

            /// </summary>

            [ConfigurationProperty(PluginCollectionProperty)]

            public PluginDataCollection Plugins

            {

                  get

                  {

                      return (PluginDataCollection)base[PluginCollectionProperty];

                  }

            }

 

    }

}


After the definition of the Configuration Section we need the collection class which contains a list of elements. If you want a list of strongly typed data elements in the config file you can use the PolymorphicConfigurationElementCollection<T> generic which is introduced by the Enterprise Library. This class was specifically designed to store lists of the following form:
<SectionName>

      <add name="blah" type="PluginData strongly typed " xxx="xxxx" xxx="xxxx" .../>

</SectionName>


You have to derive from
PolymorphicConfigurationElementCollection and implement the RetrieveElementConfigurationElementType where you retrieve the data type which is responsible for the ser/deserialization of the other attributes of this node. Error handling code has been omitted. Please have a look at e.g. the Logging Application Block of Entlib to see the correct error handling.
 
PluginDataCollection.cs

using System;

using System.Collections.Generic;

using System.Text;

using System.Xml;

using System.Configuration;

using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

 

 

namespace EntlibInjection

{

    public class PluginDataCollection : PolymorphicConfigurationElementCollection<PluginData>

    {

            /// <summary>

            /// Returns the <see cref="ConfigurationElement"/> type to created for the current xml node.

            /// </summary>

            /// <remarks>

            /// The <see cref="PluginData"/> include the configuration object type as a serialized attribute.

            /// </remarks>

            /// <param >

            protected override Type RetrieveConfigurationElementType(XmlReader reader)

            {

                 return typeof(PluginData);

            }

 

    }

}

I have simplified the RetrieveConfigurationElementType a lot compared to the normally used strongly typed name which should be specified to allow versioning of you configuration node data types. Please do NOT use this shortcut in production environments. If you do not want strong names for your data types then the PolymorphicConfigurationElementCollection<xxx> is not the right choice for your problem. Instead a direct derivate of ConfigurationElementCollection is the better alternative for you. Do not ask me how to figure out with which version of PluginData you App.Config was created when you do not use strong names for your data types.This can be an important issue if you plan e.g. to create configuration converters from one version to the next. Please have a look at the Logging Block code e.g. TraceListenerDataCollection how the PolymorphicConfigurationElementCollection<xxx> is correctly implemented. Ok so much for versioning. Now we can create our PluginData class which contains the plugin data type and an external config file which contains the plugin configuration. If it is not specified we assume the the plugin configuration is located in the App.config file. This can be  implemented by switching from SystemConfigurationSource to FileConfiguratonSource and put the plugin config file into it.

 PluginData.cs

using System;

using System.ComponentModel;

using System.Collections.Generic;

using System.Text;

using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

using System.Configuration;

 

 

namespace EntlibInjection

{

    public class PluginData : NameTypeConfigurationElement

    {

        public const string PluginTypeProperty = "plugintype";

        public const string PluginConfigProperty = "cfgfile";

 

 

          private static IDictionary<string, string> emptyAttributes = new Dictionary<string, string>(0);

 

     

            public PluginData()

            {

            }

 

            protected PluginData(string name, Type PluginType)

                  : base(name, PluginType)

            {

                this.PluginType = this.GetType();

            }

 

 

 

            [ConfigurationProperty(PluginConfigProperty, DefaultValue="", IsRequired = false)]

            public string ConfigFile

            {

                  get

                  {

                     return (string)this[PluginConfigProperty];

                  }

                  set

                  {

                     this[PluginConfigProperty] = value;

                  }

            }

 

 

            [ConfigurationProperty(PluginTypeProperty, IsRequired= true)]

            [TypeConverter(typeof(AssemblyQualifiedTypeNameConverter))]

            public Type PluginType

            {

                  get

                  {

                        return (Type)this[PluginTypeProperty];

                  }

                  set

                  {

                        this[PluginTypeProperty] = value;

                  }

            }

    }

}

 

To load the configuration form a config file you can use the FileConfigurationSource from the Enterprise Library and you are ready to rockn roll.

         FileConfigurationSource configurationSource = new FileConfigurationSource(“2D.config”);

         PluginManagerConfiguration.GetPluginSettings(configurationSource);

There are many new things within the System.Configuration namespace which this article tries to show you how the can be used. I hope this article gives you enough starting points to jump up on the .NET 2.0 wagon and the new Enterprise Library. One last thing: User settings are not supported by the Enterprise Library. But you can fake this by creating a config file in %APPDATA%\MyEntlibApp\<MyEntlibApp Assembly Version>\User.config and load it from there. To make this work you need a loaded user profile which is not always present e.g.  System Service. In this case you need to load some trusted user profile to make it work.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值