Добавление пользовательских атрибутов в раздел «Конфигурация настраиваемого поставщика» в app.config - PullRequest
3 голосов
/ 08 февраля 2012

Я слежу за этой замечательной статьей о том, как создать среду провайдера в .NET

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

   <configuration>
     <configSections>
        <section name="data" type="DataProviderConfigurationSection" />
      </configSections>
      <data defaultProvider="MyDataProvider">
         <providers>
            <add name="MydataProvider" type="MyDataProvider"  />
         </providers>
      </data>
   </configuration>

Где элемент <add/> позволяет вам определить поставщика.

Однако я хотел бы знать, как расширить запись add с помощью пользовательских атрибутов.

Например:

<providers>
  <add name="MydataProvider" type="MyDataProvider" myProperty="myValue" myProperty2="myValue2" ... />
</providers>

Любая помощь будет принята с благодарностью.

Ответы [ 4 ]

7 голосов
/ 09 февраля 2012

Вот что я наконец нашел. Это очень конкретный вопрос о расширении элемента дополнительными атрибутами и о том, как их обрабатывать при реализации Provider Framework . Все ответы о пользовательских разделах конфигурации в порядке, но не относятся к исходному вопросу.

Если вам нужно реализовать пользовательский поставщик, например MembershipProvider, но для собственных целей, вам обязательно нужно прочитать эту статью: Создание собственной структуры поставщика

Это отличное чтение. Теперь, если вам нужно расширить элемент своими атрибутами, вот что вам нужно изменить ...

1) Далее приведен код, обсуждаемый в статье (возможны некоторые изменения):

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


    public abstract class DataProvider : ProviderBase
    {
        // Define the methods to be used by the provider.  These are custom methods to your own provider.
        public abstract void Get();
        public abstract void Delete();
    }

    public class DataProviderCollection : ProviderCollection { }




    //The name is typically the same as the abstract class, minus the Provider part. Sticking to our (fake) example. we'd have a static class called Data.
    public static class Data
    {
        private static bool _isInitialized = false;

        private static DataProvider _provider;
        public static DataProvider Provider
        {
            get
            {
                Initialize();
                return _provider;
            }
        }

        private static DataProviderCollection _providers;
        public static DataProviderCollection Providers
        {
            get
            {
                Initialize();
                return _providers;
            }
        }

        private static void Initialize()
        {
            DataProviderConfigurationSection dataConfig = null;

            if (!_isInitialized)
            {
                // get the configuration section for the feature
                dataConfig = (DataProviderConfigurationSection)ConfigurationManager.GetSection("data");

                if (dataConfig == null)
                {
                    throw new ConfigurationErrorsException("Data is not configured to be used with this application");
                }

                _providers = new DataProviderCollection();

                // use the ProvidersHelper class to call Initialize() on each provider
                ProvidersHelper.InstantiateProviders(dataConfig.Providers, _providers, typeof(DataProvider));

                // set a reference to the default provider
                _provider = _providers[dataConfig.DefaultProvider] as DataProvider;

                _isInitialized = true;
            }
        }

        public static void Get()
        {
            Initialize();
            if (_provider != null)
            {
                _provider.Get();
            }
        }

        public static void Delete()
        {
            Initialize();
            if (_provider != null)
            {
                _provider.Delete();
            }
        }
    }

    public class MyDataProvider : DataProvider
    {




        public override void Get()
        {
            // Get Code
        }

        public override void Delete()
        {
            // Delete Code
        }
    }

    public class DataProviderConfigurationSection : ConfigurationSection
    {
        public DataProviderConfigurationSection()
        {
            _defaultProvider = new ConfigurationProperty("defaultProvider", typeof(string), null);
            _providers = new ConfigurationProperty("providers", typeof(ProviderSettingsCollection), null);
            _properties = new ConfigurationPropertyCollection();

            _properties.Add(_providers);
            _properties.Add(_defaultProvider);
        }

        private readonly ConfigurationProperty _defaultProvider;
        [ConfigurationProperty("defaultProvider")]
        public string DefaultProvider
        {
            get { return (string)base[_defaultProvider]; }
            set { base[_defaultProvider] = value; }
        }

        private readonly ConfigurationProperty _providers;
        [ConfigurationProperty("providers")]
        public ProviderSettingsCollection Providers
        {
            get { return (ProviderSettingsCollection)base[_providers]; }
        }

        private ConfigurationPropertyCollection _properties;
        protected override ConfigurationPropertyCollection Properties
        {
            get { return _properties; }
        }
    }

    public static class ProvidersHelper
    {
        private static Type providerBaseType = typeof(ProviderBase);

        /// <summary>
        /// Instantiates the provider.
        /// </summary>
        /// <param name="providerSettings">The settings.</param>
        /// <param name="providerType">Type of the provider to be instantiated.</param>
        /// <returns></returns>
        public static ProviderBase InstantiateProvider(ProviderSettings providerSettings, Type providerType)
        {
            ProviderBase base2 = null;
            try
            {
                string str = (providerSettings.Type == null) ? null : providerSettings.Type.Trim();
                if (string.IsNullOrEmpty(str))
                {
                    throw new ArgumentException("Provider type name is invalid");
                }
                Type c = Type.GetType(str, true, true);
                if (!providerType.IsAssignableFrom(c))
                {
                    throw new ArgumentException(String.Format("Provider must implement type {0}.", providerType.ToString()));
                }
                base2 = (ProviderBase)Activator.CreateInstance(c);
                NameValueCollection parameters = providerSettings.Parameters;
                NameValueCollection config = new NameValueCollection(parameters.Count, StringComparer.Ordinal);
                foreach (string str2 in parameters)
                {
                    config[str2] = parameters[str2];
                }
                base2.Initialize(providerSettings.Name, config);
            }
            catch (Exception exception)
            {
                if (exception is ConfigurationException)
                {
                    throw;
                }
                throw new ConfigurationErrorsException(exception.Message,
                    providerSettings.ElementInformation.Properties["type"].Source,
                    providerSettings.ElementInformation.Properties["type"].LineNumber);
            }
            return base2;
        }

        public static void InstantiateProviders(ProviderSettingsCollection providerSettings, ProviderCollection providers, Type type)
        {
            foreach (ProviderSettings settings in providerSettings)
            {
                providers.Add(ProvidersHelper.InstantiateProvider(settings, type));
            }
        }
    }

2) Это файл конфигурации, который вы используете для приведенного выше кода:

  <configuration>
    <configSections>
      <section name="data" type="DataProviderConfigurationSection" />
    </configSections>
    <data defaultProvider="MyDataProvider">
      <providers>
        <add name="MydataProvider" type="MyDataProvider"  />
      </providers>
    </data>
  </configuration>

3) Теперь вот что вам нужно изменить, чтобы использовать чтение атрибутов в элементе <add> в файле конфигурации.

    public abstract class DataProvider : ProviderBase
    {

        public string MyAttribute1 { get; set; }
        public string MyAttribute2 { get; set; }
        public string MyAttribute3 { get; set; }

        // Define the methods to be used by the provider.  These are custom methods to your own provider.
        public abstract void Get();
        public abstract void Delete();

        public override void Initialize(string name, NameValueCollection config)
        {

            MyAttribute1 = config["MyAttribute1"];
            MyAttribute2 = config["MyAttribute2"];
            MyAttribute3 = config["MyAttribute3"];

            base.Initialize(name, config);
        }
    }

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

  <configuration>
    <configSections>
      <section name="data" type="DataProviderConfigurationSection" />
    </configSections>
    <data defaultProvider="MyDataProvider">
      <providers>
        <add name="MydataProvider" type="MyDataProvider" MyAttribute1="MyValue1" MyAttribute2="MyValue2"   />
      </providers>
    </data>
  </configuration>

И, в качестве бонуса, вот юнит-тест для проверки его работоспособности:

[TestMethod]
public void RunMyDataProviderTest()
        {
            DataProvider dataProvider = Data.Provider;

            Assert.IsInstanceOfType(dataProvider, typeof(MyDataProvider));

            Assert.AreEqual(dataProvider.MyAttribute1, "MyValue1");
            Assert.AreEqual(dataProvider.MyAttribute2, "MyValue2");
}
1 голос
/ 08 февраля 2012

Вы можете использовать ConfigurationProperty и ProviderBase

0 голосов
/ 08 февраля 2012

Вам необходимо создать пользовательскую реализацию ConfigurationSection , которая позволит вам создать настроенное дерево конфигурации, как вы предоставили.

0 голосов
/ 08 февраля 2012

Как:

<add name="countingCfg" maxRequestNumber="10" countingTimeRange="00:00:10" countingTimeAccuracy="00:00:02" />

C # коды:

/// <summary>
/// counting
/// </summary>
public class CountingStrategyConfigurationElement : StrategyConfigurationElement
{
    /// <summary>
    /// constructor
    /// </summary>
    public CountingStrategyConfigurationElement() { }
    /// <summary>
    /// constructor
    /// </summary>
    public CountingStrategyConfigurationElement(string name) : base(name) { }
    /// <summary>
    /// The max number of requests
    /// </summary>
    [ConfigurationProperty("maxRequestNumber", IsKey = false, IsRequired = true)]
    public int MaxRequestNumber
    {
        get
        {
            return (int)this["maxRequestNumber"];
        }
        set
        {
            this["maxRequestNumber"] = value;
        }
    }
    /// <summary>
    /// Counting request in this range of time
    /// </summary>
    [ConfigurationProperty("countingTimeRange", IsKey = false, IsRequired = true)]
    public TimeSpan CountingTimeRange
    {
        get
        {
            return (TimeSpan)this["countingTimeRange"];
        }
        set
        {
            this["countingTimeRange"] = value;
        }
    }
    /// <summary>
    /// Counting Time Accuracy
    /// </summary>
    [ConfigurationProperty("countingTimeAccuracy", IsKey = false, IsRequired = true)]
    public TimeSpan CountingTimeAccuracy
    {
        get
        {
            return (TimeSpan)this["countingTimeAccuracy"];
        }
        set
        {
            this["countingTimeAccuracy"] = value;
        }
    }
}
...