একটি কনফিগারেশন এলিমেন্ট কালেকশন সহ একটি কনফিগারেশনসেকশন কীভাবে প্রয়োগ করা যায়


166

আমি একটি প্রকল্পে একটি কাস্টম কনফিগারেশন বিভাগ বাস্তবায়নের চেষ্টা করছি এবং আমি যে ব্যতিক্রমগুলি বুঝতে পারি না তার বিরুদ্ধে চালিয়ে যাচ্ছি। আমি আশা করছি যে কেউ এখানে শূন্যস্থান পূরণ করতে পারে।

আমার কাছে এ App.configরকম দেখাচ্ছে:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="ServicesSection" type="RT.Core.Config.ServicesConfigurationSectionHandler, RT.Core"/>
    </configSections>
    <ServicesSection type="RT.Core.Config.ServicesSection, RT.Core">
            <Services>
                <AddService Port="6996" ReportType="File" />
                <AddService Port="7001" ReportType="Other" />
            </Services>
        </ServicesSection>
</configuration>

আমার ServiceConfigমতো একটি সংজ্ঞা দেওয়া হয়েছে:

public class ServiceConfig : ConfigurationElement
  {
    public ServiceConfig() {}

    public ServiceConfig(int port, string reportType)
    {
      Port = port;
      ReportType = reportType;
    }

    [ConfigurationProperty("Port", DefaultValue = 0, IsRequired = true, IsKey = true)]
    public int Port 
    {
      get { return (int) this["Port"]; }
      set { this["Port"] = value; }
    }

    [ConfigurationProperty("ReportType", DefaultValue = "File", IsRequired = true, IsKey = false)]
    public string ReportType
    {
      get { return (string) this["ReportType"]; }
      set { this["ReportType"] = value; }
    }
  }

এবং আমি এর ServiceCollectionমত একটি সংজ্ঞায়িত আছে :

public class ServiceCollection : ConfigurationElementCollection
  {
    public ServiceCollection()
    {
      Console.WriteLine("ServiceCollection Constructor");
    }

    public ServiceConfig this[int index]
    {
      get { return (ServiceConfig)BaseGet(index); }
      set
      {
        if (BaseGet(index) != null)
        {
          BaseRemoveAt(index);
        }
        BaseAdd(index, value);
      }
    }

    public void Add(ServiceConfig serviceConfig)
    {
      BaseAdd(serviceConfig);
    }

    public void Clear()
    {
      BaseClear();
    }

    protected override ConfigurationElement CreateNewElement()
    {
      return new ServiceConfig();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
      return ((ServiceConfig) element).Port;
    }

    public void Remove(ServiceConfig serviceConfig)
    {
      BaseRemove(serviceConfig.Port);
    }

    public void RemoveAt(int index)
    {
      BaseRemoveAt(index);
    }

    public void Remove(string name)
    {
      BaseRemove(name);
    }
  }

আমি যে অংশটি মিস করছি তা হ্যান্ডলারের জন্য কী করা উচিত। মূলত, আমি একটি বাস্তবায়নের চেষ্টা করেছি IConfigurationSectionHandlerতবে দুটি জিনিস পেয়েছি:

  1. এটা কাজ করে না
  2. এটি হ্রাস করা হয়েছে।

আমি কী করতে হবে তা সম্পর্কে এখন পুরোপুরি হারিয়ে গেছে তাই আমি কনফিগার থেকে আমার ডেটা পড়তে পারি। কোন সাহায্য দয়া করে!


আমি এই কাজ পেতে পারি না। আমি আরটি.কোর.কমফিগ. সার্ভিসেসেকশনটি দেখতে পছন্দ করি। আমি স্বীকৃত উত্তর থেকে কোডটি ব্যবহার করার পরেও সবেমাত্র অজানা উপাদান 'অ্যাড সার্ভিস' পাই।
sirank

আমি এটিকে প্রথমটিও মিস করেছি - এই অংশ: [কনফিগারেশন সংগ্রহ (টাইপফ (সার্ভিস ক্লেকশন), অ্যাড আইটেমনেম = "অ্যাড", ক্লিয়ারআইটেমনাম = "ক্লিয়ার", রিয়েলটাইমনেম = "অপসারণ")] অ্যাডটাইমনেমটি মিলেছে তাই যদি আপনি "অ্যাড" পরিবর্তন করেন "
অ্যাড সার্ভিস

উত্তর:


188

পূর্ববর্তী উত্তরটি সঠিক তবে আমি আপনাকে সমস্ত কোডও দেব।

আপনার app.config এর মতো দেখতে হবে:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <configSections>
      <section name="ServicesSection" type="RT.Core.Config.ServiceConfigurationSection, RT.Core"/>
   </configSections>
   <ServicesSection>
      <Services>
         <add Port="6996" ReportType="File" />
         <add Port="7001" ReportType="Other" />
      </Services>
   </ServicesSection>
</configuration>

আপনার ServiceConfigএবং ServiceCollectionক্লাসগুলি অপরিবর্তিত রয়েছে।

আপনার নতুন ক্লাস দরকার:

public class ServiceConfigurationSection : ConfigurationSection
{
   [ConfigurationProperty("Services", IsDefaultCollection = false)]
   [ConfigurationCollection(typeof(ServiceCollection),
       AddItemName = "add",
       ClearItemsName = "clear",
       RemoveItemName = "remove")]
   public ServiceCollection Services
   {
      get
      {
         return (ServiceCollection)base["Services"];
      }
   }
}

এবং যে কৌশল করা উচিত। এটি গ্রাস করতে আপনি ব্যবহার করতে পারেন:

ServiceConfigurationSection serviceConfigSection =
   ConfigurationManager.GetSection("ServicesSection") as ServiceConfigurationSection;

ServiceConfig serviceConfig = serviceConfigSection.Services[0];

10
[Add|Remove|Clear]ItemNameউপর বৈশিষ্ট্য ConfigurationCollectionবৈশিষ্ট্য কারণ "যোগ" / "স্পষ্ট" / "সরান" ইতিমধ্যে XML উপাদান ডিফল্ট নাম, সত্যিই এই ক্ষেত্রে প্রয়োজনীয় নয়।
উইম কোয়েন

2
ট্যাগগুলি যাতে যুক্ত না হয় তাই আমি কীভাবে এটি কাজ করব? এগুলি যুক্ত হলে এটি কেবল কাজ করবে বলে মনে হয়। এটি হবে কাজ না যদি এটা <পরিষেবা পোর্ট = "6996" ReportType = "ফাইল" /> অথবা <পরিষেবা পোর্ট = "7001" ReportType = "অন্যান্য" /> ছিল
JonathanWolfson

7
@JonathanWolfson: শুধু AddItemName = "যোগ করুন" পরিবর্তন AddItemName = "পরিষেবা" থেকে
Mubashar

এটি কি এখনও .NET 4.5?
ক্রাশ করুন

6
@ ক্রাশ: হ্যাঁ। নেট এর ধুলাবালি কোণে খুব বেশি পরিবর্তন হয় নি।
রাসেল ম্যাকক্লুর

84

আপনি যদি নীচের মত একটি কাস্টম কনফিগারেশন বিভাগ খুঁজছেন

<CustomApplicationConfig>
        <Credentials Username="itsme" Password="mypassword"/>
        <PrimaryAgent Address="10.5.64.26" Port="3560"/>
        <SecondaryAgent Address="10.5.64.7" Port="3570"/>
        <Site Id="123" />
        <Lanes>
          <Lane Id="1" PointId="north" Direction="Entry"/>
          <Lane Id="2" PointId="south" Direction="Exit"/>
        </Lanes> 
</CustomApplicationConfig>

তারপরে আপনি কনফিগারেশন বিভাগটির আমার বাস্তবায়নটি ব্যবহার করতে পারেন যাতে System.Configurationআপনার প্রকল্পে সমাবেশ রেফারেন্স যুক্ত শুরু করতে পারেন

আমি যে প্রতিটি নেস্টেড উপাদানগুলি ব্যবহার করেছি সেটির দিকে নজর দিন, প্রথমটি হ'ল দুটি বৈশিষ্ট্যযুক্ত শংসাপত্র যাতে প্রথমে এটি যুক্ত করা যাক

শংসাপত্র উপাদান

public class CredentialsConfigElement : System.Configuration.ConfigurationElement
    {
        [ConfigurationProperty("Username")]
        public string Username
        {
            get 
            {
                return base["Username"] as string;
            }
        }

        [ConfigurationProperty("Password")]
        public string Password
        {
            get
            {
                return base["Password"] as string;
            }
        }
    }

প্রাথমিক এজেন্ট এবং মাধ্যমিক এজেন্ট

উভয়েরই একই বৈশিষ্ট্য রয়েছে এবং প্রাথমিক এবং একটি ব্যর্থভারের জন্য সার্ভারের সেটগুলির ঠিকানার মতো মনে হয়, সুতরাং আপনাকে কেবল নিম্নলিখিত দুটি ব্যক্তির জন্য একটি উপাদান শ্রেণি তৈরি করতে হবে

public class ServerInfoConfigElement : ConfigurationElement
    {
        [ConfigurationProperty("Address")]
        public string Address
        {
            get
            {
                return base["Address"] as string;
            }
        }

        [ConfigurationProperty("Port")]
        public int? Port
        {
            get
            {
                return base["Port"] as int?;
            }
        }
    }

আমি এই পোস্টে পরে একটি শ্রেণীর সাথে কীভাবে দুটি পৃথক উপাদান ব্যবহার করব তা ব্যাখ্যা করব, আসুন সাইট আইড এড়িয়ে চলুন কারণ এতে কোনও পার্থক্য নেই। আপনাকে কেবলমাত্র একটি সম্পত্তি দিয়ে উপরের মত একটি শ্রেণি তৈরি করতে হবে। লেনস সংগ্রহটি কীভাবে কার্যকর করা যায় তা আমাদের দেখুন

এটি দুটি অংশে বিভক্ত হয় প্রথমে আপনাকে একটি উপাদান বাস্তবায়ন শ্রেণি তৈরি করতে হবে তারপরে আপনাকে সংগ্রহ উপাদান উপাদান তৈরি করতে হবে

LaneConfigElement

public class LaneConfigElement : ConfigurationElement
    {
        [ConfigurationProperty("Id")]
        public string Id
        {
            get
            {
                return base["Id"] as string;
            }
        }

        [ConfigurationProperty("PointId")]
        public string PointId
        {
            get
            {
                return base["PointId"] as string;
            }
        }

        [ConfigurationProperty("Direction")]
        public Direction? Direction
        {
            get
            {
                return base["Direction"] as Direction?;
            }
        }
    }

    public enum Direction
    { 
        Entry,
        Exit
    }

আপনি খেয়াল করতে পারেন যে এর একটি বৈশিষ্ট্য LanElementহল একটি এনুমুরেশন এবং আপনি যদি কনফিগারেশনের অন্য কোনও মান ব্যবহার করার চেষ্টা করেন যা গণনা অ্যাপ্লিকেশনটিতে সংজ্ঞায়িত করা হয় না তবে System.Configuration.ConfigurationErrorsExceptionএটি প্রারম্ভকালে একটি নিক্ষেপ করবে । ঠিক আছে সংগ্রহ সংজ্ঞাতে এগিয়ে চলুন

[ConfigurationCollection(typeof(LaneConfigElement), AddItemName = "Lane", CollectionType = ConfigurationElementCollectionType.BasicMap)]
    public class LaneConfigCollection : ConfigurationElementCollection
    {
        public LaneConfigElement this[int index]
        {
            get { return (LaneConfigElement)BaseGet(index); }
            set
            {
                if (BaseGet(index) != null)
                {
                    BaseRemoveAt(index);
                }
                BaseAdd(index, value);
            }
        }

        public void Add(LaneConfigElement serviceConfig)
        {
            BaseAdd(serviceConfig);
        }

        public void Clear()
        {
            BaseClear();
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new LaneConfigElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((LaneConfigElement)element).Id;
        }

        public void Remove(LaneConfigElement serviceConfig)
        {
            BaseRemove(serviceConfig.Id);
        }

        public void RemoveAt(int index)
        {
            BaseRemoveAt(index);
        }

        public void Remove(String name)
        {
            BaseRemove(name);
        }

    }

আপনি খেয়াল করতে পারেন যে আমি AddItemName = "Lane"আপনার সংগ্রহ এন্ট্রি আইটেমটির জন্য আপনি যা পছন্দ করতে পারেন তা চয়ন করতে পারেন, আমি ডিফল্টটিকে "যুক্ত" ব্যবহার করতে পছন্দ করি তবে আমি কেবল এই পোস্টের স্বার্থে এটি পরিবর্তন করেছি।

এখন আমাদের নেস্টেড এলিমেন্টগুলির সবগুলি কার্যকর করা হয়েছে এখন আমাদের ক্লাসে যারা বাস্তবায়ন করতে হবে তাদের সকলকে একত্রিত করা উচিত System.Configuration.ConfigurationSection

CustomApplicationConfigSection

public class CustomApplicationConfigSection : System.Configuration.ConfigurationSection
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(CustomApplicationConfigSection));
        public const string SECTION_NAME = "CustomApplicationConfig";

        [ConfigurationProperty("Credentials")]
        public CredentialsConfigElement Credentials
        {
            get
            {
                return base["Credentials"] as CredentialsConfigElement;
            }
        }

        [ConfigurationProperty("PrimaryAgent")]
        public ServerInfoConfigElement PrimaryAgent
        {
            get
            {
                return base["PrimaryAgent"] as ServerInfoConfigElement;
            }
        }

        [ConfigurationProperty("SecondaryAgent")]
        public ServerInfoConfigElement SecondaryAgent
        {
            get
            {
                return base["SecondaryAgent"] as ServerInfoConfigElement;
            }
        }

        [ConfigurationProperty("Site")]
        public SiteConfigElement Site
        {
            get
            {
                return base["Site"] as SiteConfigElement;
            }
        }

        [ConfigurationProperty("Lanes")]
        public LaneConfigCollection Lanes
        {
            get { return base["Lanes"] as LaneConfigCollection; }
        }
    }

এখন আপনি দেখতে পাচ্ছেন যে নামের সহ আমাদের দুটি সম্পত্তি রয়েছে PrimaryAgentএবং SecondaryAgentউভয়েরই একই ধরণের রয়েছে এখন আপনি সহজেই বুঝতে পারবেন কেন আমাদের এই দুটি উপাদানটির বিরুদ্ধে কেবল একটি বাস্তবায়ন শ্রেণি ছিল।

আপনি নতুনভাবে উদ্ভাবিত কনফিগারেশন বিভাগটি আপনার অ্যাপ্লিকেশনটিতে ব্যবহার করার আগে আপনাকে নিজের অ্যাপ্লিকেশনটি বলতে হবে যে আপনি নিজের কনফিগারেশন বিভাগটি আবিষ্কার করেছেন এবং কিছুটা শ্রদ্ধা জানান, আপনাকে নিম্নলিখিত লাইন যুক্ত করতে হবে app.config এ (রুট ট্যাগ শুরুর ঠিক পরে হতে পারে)।

<configSections>
    <section name="CustomApplicationConfig" type="MyNameSpace.CustomApplicationConfigSection, MyAssemblyName" />
  </configSections>

দ্রষ্টব্য: মায়াস্প্যাশনের নাম .dll ছাড়াই হওয়া উচিত যেমন যদি আপনার অ্যাসেম্বলি ফাইলের নাম myDll.dll হয় তবে myDll.dll এর পরিবর্তে myDll ব্যবহার করুন

এই কনফিগারেশনটি পুনরুদ্ধার করতে আপনার অ্যাপ্লিকেশনটিতে যে কোনও জায়গায় কোডের নীচের লাইনটি ব্যবহার করুন

CustomApplicationConfigSection config = System.Configuration.ConfigurationManager.GetSection(CustomApplicationConfigSection.SECTION_NAME) as CustomApplicationConfigSection;

আমি আশা করি উপরের পোস্টটি আপনাকে কিছুটা জটিল ধরণের কাস্টম কনফিগার বিভাগগুলির সাথে শুরু করতে সহায়তা করবে।

শুভ কোডিং :)

**** সম্পাদনা করুন **** LaneConfigCollectionআপনাকে লিনিক্যু সক্ষম করতে কার্যকর করতে হবেIEnumerable<LaneConfigElement>

এবং নিম্নলিখিত বাস্তবায়ন যুক্ত করুন GetEnumerator

public new IEnumerator<LaneConfigElement> GetEnumerator()
        {
            int count = base.Count;
            for (int i = 0; i < count; i++)
            {
                yield return base.BaseGet(i) as LaneConfigElement;
            }
        }

যারা এখনও সম্পর্কে বিভ্রান্ত জন্য কিভাবে ফলন সত্যিই পড়া কাজ করে এই চমৎকার নিবন্ধ

উপরের নিবন্ধ থেকে নেওয়া দুটি মূল পয়েন্ট

এটি সত্যই পদ্ধতিটির কার্যকারিতা শেষ করে না। ফলন ফেরত পদ্ধতিটির কার্যনির্বাহীকরণকে বিরতি দেয় এবং পরের বার আপনি যখন এটিকে ডাকবেন (পরবর্তী অঙ্কের মানের জন্য), পদ্ধতিটি সর্বশেষ ফলন রিটার্ন কল থেকে চালিয়ে যেতে থাকবে। আমার মনে হয় এটি কিছুটা বিভ্রান্তিকর মনে হচ্ছে ... (শাই ফ্রেডম্যান)

ফলন। নেট রানটাইমের কোনও বৈশিষ্ট্য নয়। এটি কেবলমাত্র একটি সি # ভাষার বৈশিষ্ট্য যা সি # সংকলক দ্বারা সাধারণ আইএল কোডে সংকলিত হয়। (লার্স কর্নেলিয়াসেন)


3
একটি সম্পূর্ণ উদাহরণ প্রদান করার জন্য ধন্যবাদ, এটি সত্যিই অনেক সাহায্য করে!
জন লিডেগ্রেন

46

এটি কনফিগারেশন সংগ্রহের জন্য জেনেরিক কোড:

public class GenericConfigurationElementCollection<T> :   ConfigurationElementCollection, IEnumerable<T> where T : ConfigurationElement, new()
{
    List<T> _elements = new List<T>();

    protected override ConfigurationElement CreateNewElement()
    {
        T newElement = new T();
        _elements.Add(newElement);
        return newElement;
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return _elements.Find(e => e.Equals(element));
    }

    public new IEnumerator<T> GetEnumerator()
    {
        return _elements.GetEnumerator();
    }
}

আপনার পরে GenericConfigurationElementCollection, আপনি এটি কনফিগার বিভাগে সহজভাবে ব্যবহার করতে পারেন (এটি আমার ডিসপ্যাচারের উদাহরণ):

public class  DispatcherConfigurationSection: ConfigurationSection
{
    [ConfigurationProperty("maxRetry", IsRequired = false, DefaultValue = 5)]
    public int MaxRetry
    {
        get
        {
            return (int)this["maxRetry"];
        }
        set
        {
            this["maxRetry"] = value;
        }
    }

    [ConfigurationProperty("eventsDispatches", IsRequired = true)]
    [ConfigurationCollection(typeof(EventsDispatchConfigurationElement), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")]
    public GenericConfigurationElementCollection<EventsDispatchConfigurationElement> EventsDispatches
    {
        get { return (GenericConfigurationElementCollection<EventsDispatchConfigurationElement>)this["eventsDispatches"]; }
    }
}

কনফিগার উপাদানটি এখানে কনফিগার করা আছে:

public class EventsDispatchConfigurationElement : ConfigurationElement
{
    [ConfigurationProperty("name", IsRequired = true)]
    public string Name
    {
        get
        {
            return (string) this["name"];
        }
        set
        {
            this["name"] = value;
        }
    }
}

কনফিগারেশন ফাইলটি দেখতে এরকম হবে:

<?xml version="1.0" encoding="utf-8" ?>
  <dispatcherConfigurationSection>
    <eventsDispatches>
      <add name="Log" ></add>
      <add name="Notification" ></add>
      <add name="tester" ></add>
    </eventsDispatches>
  </dispatcherConfigurationSection>

আশা করি এটি সাহায্য করবে!


শান্ত! একই সম্পর্কে ভাবছিলাম এবং খুঁজে পেয়েছি যে আমি একা নই। এমএস সকল এফসিএল
কনফিগারেশনের

আইটেমগুলির জন্য বেসিক ম্যাপ দিয়ে কীভাবে এটি করা যায় সে সম্পর্কে কোনও পরামর্শ? আমি যদি এড়াতে পারি তবে আমি অ্যাড বাস্তবায়ন করতে চাই না।
SpaceCowboy74

28

যারা ম্যানুয়ালি এই সমস্ত কনফিগারেশন বয়লারপ্লেট না লিখতে পছন্দ করেন তাদের পক্ষে একটি সহজ বিকল্প ...

1) নুগেট থেকে নারডল.আউটকনফিগ ইনস্টল করুন

2) আপনার সার্ভিস কনফিগ টাইপ সংজ্ঞায়িত করুন (হয় কংক্রিট ক্লাস বা কেবল একটি ইন্টারফেস, হয় করবে)

public interface IServiceConfiguration
{
    int Port { get; }
    ReportType ReportType { get; }
}

3) সংগ্রহটি ধরার জন্য আপনার এক ধরণের প্রয়োজন হবে, যেমন

public interface IServiceCollectionConfiguration
{
    IEnumerable<IServiceConfiguration> Services { get; } 
}

৪) কনফিগার বিভাগটি এভাবে যুক্ত করুন (উট কেস নামকরণ নোট করুন)

<configSections>
  <section name="serviceCollection" type="Nerdle.AutoConfig.Section, Nerdle.AutoConfig"/>
</configSections>

<serviceCollection>
  <services>
    <service port="6996" reportType="File" />
    <service port="7001" reportType="Other" />
  </services>
</serviceCollection>

5) অটোকনফিগ সহ মানচিত্র

var services = AutoConfig.Map<IServiceCollectionConfiguration>();

5
এই উত্তরের জন্য Thank
শ্বরের

যে লোকেরা কেবল এটি
সম্পাদন

5

থেকে উত্তরাধিকার সূত্রে প্রাপ্ত করার চেষ্টা করুন ConfigurationSection । ফিল হ্যাকের এই ব্লগ পোস্টটির একটি উদাহরণ রয়েছে।

আইকনফাইগ্রেশনসেকশনহ্যান্ডলারের ডকুমেন্টেশন অনুসারে নিশ্চিত হয়েছে :

.NET ফ্রেমওয়ার্ক সংস্করণ ২.০ এবং তারপরে, সম্পর্কিত কনফিগারেশন বিভাগ হ্যান্ডলারটি বাস্তবায়নের জন্য আপনার অবশ্যই কনফিগারেশন বিভাগ থেকে নেওয়া উচিত।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.