在我自己的自定义 appSettings 上使用 foreach 所需的代码

发布于 2024-08-27 17:00:40 字数 1169 浏览 4 评论 0原文

我搜索了该网站,但没有找到我想要的内容。接近,但没有雪茄。

基本上我想要一个像这样的配置部分:

<configSections>
    <section name="PhoneNotificationsSection" type="Alerts.PhoneAlertConfigSection,Alerts,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/>    
</configSections>
<PhoneNotificationsSection>
  <phones>
    <add phone="MyMobile" value="[email protected]" />
    <add phone="OtherMobile" value="[email protected]" />
  </phones>
</PhoneNotificationsSection>

然后我想在我的 appSettings 消费代码中,能够编写这样的东西(伪代码):

foreach (phone p in phones)
{
   //'phone' attribute is just helpful/descriptive
   DoSomething(p.value);
}

我已经做了足够的研究知道我可能需要一些我自己的类实现和/或继承某些配置类以使上述代码成为可能。我只是还没有找到任何可以清楚地演示这种情况以及如何为其编码的内容 - 当我尝试学习整个 .NET 配置世界时,我的大脑开始受伤。有人有一些像我正在寻找的代码可以分享吗?

I've searched the site and haven't found exactly what I'm looking for. Close, but no cigar.

Basically I want to have a config section like this:

<configSections>
    <section name="PhoneNotificationsSection" type="Alerts.PhoneAlertConfigSection,Alerts,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/>    
</configSections>
<PhoneNotificationsSection>
  <phones>
    <add phone="MyMobile" value="[email protected]" />
    <add phone="OtherMobile" value="[email protected]" />
  </phones>
</PhoneNotificationsSection>

Then I'd like to, in my appSettings consuming code, be able to write something like this (pseudo code):

foreach (phone p in phones)
{
   //'phone' attribute is just helpful/descriptive
   DoSomething(p.value);
}

I've done enough research to know I probably need a few of my own classes that implement and/or inherit from certain Configuration classes to make the above code possible. I just haven't found anything that clearly demonstrates this scenario and how to code for it - and when I try to learn the whole .NET configuration world my brain starts to hurt. Anyone have some code like what I'm looking for that they can share?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蛮可爱 2024-09-03 17:00:40

我曾经写过类似的内容,作为 C# 课程的示例。在我看来,它主要展示了 .NET 配置子系统是多么糟糕,尽管代码确实有效。我没有根据您的设置进行调整,因为很容易引入错误,并且到目前为止 SO 编辑器不会验证发布的代码示例;)

首先,配置部分声明:

    <configSections>
        <section name="passwordSafe"
                 type="Codeworks.PasswordSafe.Model.Configuration.PasswordSafeSection, Codeworks.PasswordSafe.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </configSections>

    <passwordSafe hashAlgorithm="SHA256">
        <users>
            <user name="mm" password="Jok2eyBcFs4y7UIAlCuLix4mLfxw2byfvHfElpmk8d8=" />
            <user name="joe" password="Jok2eyBcFs4y7UIAlCuLix4mLfxw2byfvHfElpmk8d8=" />
        </users>
    </passwordSafe>

为了匹配上面的代码片段,我们首先需要配置部分:

    public class PasswordSafeSection : ConfigurationSection
    {
        #region Static Accessors
        /// <summary>
        /// Gets the configuration section using the default element name.
        /// </summary>
        public static PasswordSafeSection GetSection()
        {
            return GetSection( "passwordSafe" );
        }
        
        /// <summary>
        /// Gets the configuration section using the specified element name.
        /// </summary>
        public static PasswordSafeSection GetSection( string sectionName )
        {
            PasswordSafeSection section = ConfigurationManager.GetSection( sectionName ) as PasswordSafeSection;
            if( section == null )
            {
                string message = string.Format( "The specified configuration section (<{0}>) was not found.", sectionName );
                throw new ConfigurationErrorsException( message );
            }    
            return section;
        }
        #endregion

        #region Configuration Properties
        [ConfigurationProperty( "hashAlgorithm" )]
        public string HashAlgorithm
        {
            get { return (string) this[ "hashAlgorithm" ]; }
            set { this[ "hashAlgorithm" ] = value; }
        }

        [ConfigurationProperty( "users", IsDefaultCollection=true )]
        public UserElementCollection Users
        {
            get { return (UserElementCollection) this[ "users" ]; }
            set { this[ "users" ] = value; }
        }

        public override bool IsReadOnly()
        {
            return false;
        }
        #endregion
    }

我们正在使用自定义元素集合,因此我们也声明一下:

    [ConfigurationCollection( typeof(UserElement), CollectionType = ConfigurationElementCollectionType.BasicMap )]
    public class UserElementCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new UserElement();
        }

        protected override string ElementName
        {
            get { return "user"; }
        }
        public override ConfigurationElementCollectionType CollectionType
        {
            get { return ConfigurationElementCollectionType.BasicMap; }
        }

        public override bool IsReadOnly()
        {
            return false;
        }

        #region Indexers
        public UserElement this[ int index ]
        {
            get { return BaseGet( index ) as UserElement; }
            set
            {
                if( BaseGet( index ) != null )
                {
                    BaseRemoveAt( index );
                }
                BaseAdd( index, value );
            }
        }

        public new UserElement this[ string name ]
        {
            get { return BaseGet( name ) as UserElement; }
        }
        #endregion

        #region Lookup Methods
        protected override object GetElementKey( ConfigurationElement element )
        {
            UserElement user = element as UserElement;
            return user != null ? user.UserName : "error";
        }

        public string GetKey( int index )
        {
            return (string) BaseGetKey( index );
        }
        #endregion

        #region Add/Remove/Clear Methods
        public void Add( UserElement item )
        {
            BaseAdd( item );
        }

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

        public void Remove( UserElement item )
        {
            BaseRemove( GetElementKey( item ) );
        }

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

        public void Clear()
        {
            BaseClear();
        }
        #endregion
    }

最后我们需要声明元素集合中使用的自定义元素:

    public class UserElement : ConfigurationElement
    {
        #region Constructors
        public UserElement()
        {
        }

        public UserElement( string userName, string passwordHash )
        {
            UserName = userName;
            PasswordHash = passwordHash;
        }
        #endregion

        #region Configuration Properties
        [ConfigurationProperty( "name", IsKey = true )]
        public string UserName
        {
            get { return (string) this[ "name" ]; }
            set { this[ "name" ] = value; }
        }

        [ConfigurationProperty( "password", IsRequired = true )]
        public string PasswordHash
        {
            get { return (string) this[ "password" ]; }
            set { this[ "password" ] = value; }
        }

        public override bool IsReadOnly()
        {
            return false;
        }
        #endregion
    }

现在,完成所有这些后,我们就可以访问配置文件了。我正在使用配置器帮助程序类来使这稍微不那么麻烦:

    public static class Configurator
    {
        #region AppSettings Helpers
        public static int SplashScreenDisplayTime
        {
            get { return Convert.ToInt32( ConfigurationManager.AppSettings[ "splash.display.msecs" ] ); }
        }
        #endregion

        #region User Helpers
        public static bool TryGetUserPasswordHash( string userName, out string passwordHash )
        {
            UserElement user = GetUser( userName );
            passwordHash = user != null ? user.PasswordHash : null;
            return ! string.IsNullOrEmpty( passwordHash );
        }

        private static UserElement GetUser( string userName )
        {
            SystemConfiguration config = GetConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal );
            PasswordSafeSection section = config.Sections[ "passwordSafe" ] as PasswordSafeSection;
            return section.Users[ userName ];
        }
        public static void AddUser( string userName, string passwordHash, string encryptionKey )
        {
            SystemConfiguration config = GetConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal );
            PasswordSafeSection section = config.Sections[ "passwordSafe" ] as PasswordSafeSection;
            UserElement user = section.Users[ userName ];
            if( user == null )
            {
                user = new UserElement( userName, passwordHash, encryptionKey );
                section.Users.Add( user );
                config.Save( ConfigurationSaveMode.Modified );
            }
        }
        public static void RemoveUser( string userName )
        {
            SystemConfiguration config = GetConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal );
            PasswordSafeSection section = config.Sections[ "passwordSafe" ] as PasswordSafeSection;
            section.Users.Remove( userName );
            config.Save( ConfigurationSaveMode.Modified );
        }
        public static void UpdateUser( string userName, string passwordHash )
        {
            SystemConfiguration config = GetConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal );
            PasswordSafeSection section = config.Sections[ "passwordSafe" ] as PasswordSafeSection;
            UserElement user = section.Users[ userName ];
            if( user != null )
            {
                user.PasswordHash = passwordHash;
                config.Save( ConfigurationSaveMode.Modified );
            }
        }
        #endregion

        #region Configuration Helpers
        private static SystemConfiguration GetConfiguration( ConfigurationUserLevel userLevel )
        {
            SystemConfiguration config = InitializeConfiguration( userLevel );
            return config;
        }

        private static SystemConfiguration InitializeConfiguration( ConfigurationUserLevel userLevel )
        {    
            SystemConfiguration config = ConfigurationManager.OpenExeConfiguration( userLevel );
            PasswordSafeSection section = config.Sections[ "passwordSafe" ] as PasswordSafeSection;
            if( section == null )
            {
                section = new PasswordSafeSection();
                section.SectionInformation.AllowExeDefinition = ConfigurationAllowExeDefinition.MachineToLocalUser;
                section.SectionInformation.ForceSave = true;
                config.Sections.Add( "passwordSafe", section );
                config.Save( ConfigurationSaveMode.Full );
            }
            return config;
        }
        #endregion
    }

希望这会有所帮助。

I've written something similar once, as an example for a C# course. In my opinion it mainly demonstrates how awful the .NET configuration subsystem is, although the code does work. I've not adapted it to your settings, as it's fairly easy to introduce a mistake and so far the SO editor does not validate posted code samples ;)

First, the configuration section declaration:

    <configSections>
        <section name="passwordSafe"
                 type="Codeworks.PasswordSafe.Model.Configuration.PasswordSafeSection, Codeworks.PasswordSafe.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </configSections>

    <passwordSafe hashAlgorithm="SHA256">
        <users>
            <user name="mm" password="Jok2eyBcFs4y7UIAlCuLix4mLfxw2byfvHfElpmk8d8=" />
            <user name="joe" password="Jok2eyBcFs4y7UIAlCuLix4mLfxw2byfvHfElpmk8d8=" />
        </users>
    </passwordSafe>

To match the above snippet we first need the configuration section:

    public class PasswordSafeSection : ConfigurationSection
    {
        #region Static Accessors
        /// <summary>
        /// Gets the configuration section using the default element name.
        /// </summary>
        public static PasswordSafeSection GetSection()
        {
            return GetSection( "passwordSafe" );
        }
        
        /// <summary>
        /// Gets the configuration section using the specified element name.
        /// </summary>
        public static PasswordSafeSection GetSection( string sectionName )
        {
            PasswordSafeSection section = ConfigurationManager.GetSection( sectionName ) as PasswordSafeSection;
            if( section == null )
            {
                string message = string.Format( "The specified configuration section (<{0}>) was not found.", sectionName );
                throw new ConfigurationErrorsException( message );
            }    
            return section;
        }
        #endregion

        #region Configuration Properties
        [ConfigurationProperty( "hashAlgorithm" )]
        public string HashAlgorithm
        {
            get { return (string) this[ "hashAlgorithm" ]; }
            set { this[ "hashAlgorithm" ] = value; }
        }

        [ConfigurationProperty( "users", IsDefaultCollection=true )]
        public UserElementCollection Users
        {
            get { return (UserElementCollection) this[ "users" ]; }
            set { this[ "users" ] = value; }
        }

        public override bool IsReadOnly()
        {
            return false;
        }
        #endregion
    }

We are using a custom element collection, so let's declare that too:

    [ConfigurationCollection( typeof(UserElement), CollectionType = ConfigurationElementCollectionType.BasicMap )]
    public class UserElementCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new UserElement();
        }

        protected override string ElementName
        {
            get { return "user"; }
        }
        public override ConfigurationElementCollectionType CollectionType
        {
            get { return ConfigurationElementCollectionType.BasicMap; }
        }

        public override bool IsReadOnly()
        {
            return false;
        }

        #region Indexers
        public UserElement this[ int index ]
        {
            get { return BaseGet( index ) as UserElement; }
            set
            {
                if( BaseGet( index ) != null )
                {
                    BaseRemoveAt( index );
                }
                BaseAdd( index, value );
            }
        }

        public new UserElement this[ string name ]
        {
            get { return BaseGet( name ) as UserElement; }
        }
        #endregion

        #region Lookup Methods
        protected override object GetElementKey( ConfigurationElement element )
        {
            UserElement user = element as UserElement;
            return user != null ? user.UserName : "error";
        }

        public string GetKey( int index )
        {
            return (string) BaseGetKey( index );
        }
        #endregion

        #region Add/Remove/Clear Methods
        public void Add( UserElement item )
        {
            BaseAdd( item );
        }

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

        public void Remove( UserElement item )
        {
            BaseRemove( GetElementKey( item ) );
        }

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

        public void Clear()
        {
            BaseClear();
        }
        #endregion
    }

And finally we need to declare the custom element used in the element collection:

    public class UserElement : ConfigurationElement
    {
        #region Constructors
        public UserElement()
        {
        }

        public UserElement( string userName, string passwordHash )
        {
            UserName = userName;
            PasswordHash = passwordHash;
        }
        #endregion

        #region Configuration Properties
        [ConfigurationProperty( "name", IsKey = true )]
        public string UserName
        {
            get { return (string) this[ "name" ]; }
            set { this[ "name" ] = value; }
        }

        [ConfigurationProperty( "password", IsRequired = true )]
        public string PasswordHash
        {
            get { return (string) this[ "password" ]; }
            set { this[ "password" ] = value; }
        }

        public override bool IsReadOnly()
        {
            return false;
        }
        #endregion
    }

Now, having all this in place we're ready to access the configuration file. I'm using a Configurator helper class to make this slightly less cumbersome:

    public static class Configurator
    {
        #region AppSettings Helpers
        public static int SplashScreenDisplayTime
        {
            get { return Convert.ToInt32( ConfigurationManager.AppSettings[ "splash.display.msecs" ] ); }
        }
        #endregion

        #region User Helpers
        public static bool TryGetUserPasswordHash( string userName, out string passwordHash )
        {
            UserElement user = GetUser( userName );
            passwordHash = user != null ? user.PasswordHash : null;
            return ! string.IsNullOrEmpty( passwordHash );
        }

        private static UserElement GetUser( string userName )
        {
            SystemConfiguration config = GetConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal );
            PasswordSafeSection section = config.Sections[ "passwordSafe" ] as PasswordSafeSection;
            return section.Users[ userName ];
        }
        public static void AddUser( string userName, string passwordHash, string encryptionKey )
        {
            SystemConfiguration config = GetConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal );
            PasswordSafeSection section = config.Sections[ "passwordSafe" ] as PasswordSafeSection;
            UserElement user = section.Users[ userName ];
            if( user == null )
            {
                user = new UserElement( userName, passwordHash, encryptionKey );
                section.Users.Add( user );
                config.Save( ConfigurationSaveMode.Modified );
            }
        }
        public static void RemoveUser( string userName )
        {
            SystemConfiguration config = GetConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal );
            PasswordSafeSection section = config.Sections[ "passwordSafe" ] as PasswordSafeSection;
            section.Users.Remove( userName );
            config.Save( ConfigurationSaveMode.Modified );
        }
        public static void UpdateUser( string userName, string passwordHash )
        {
            SystemConfiguration config = GetConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal );
            PasswordSafeSection section = config.Sections[ "passwordSafe" ] as PasswordSafeSection;
            UserElement user = section.Users[ userName ];
            if( user != null )
            {
                user.PasswordHash = passwordHash;
                config.Save( ConfigurationSaveMode.Modified );
            }
        }
        #endregion

        #region Configuration Helpers
        private static SystemConfiguration GetConfiguration( ConfigurationUserLevel userLevel )
        {
            SystemConfiguration config = InitializeConfiguration( userLevel );
            return config;
        }

        private static SystemConfiguration InitializeConfiguration( ConfigurationUserLevel userLevel )
        {    
            SystemConfiguration config = ConfigurationManager.OpenExeConfiguration( userLevel );
            PasswordSafeSection section = config.Sections[ "passwordSafe" ] as PasswordSafeSection;
            if( section == null )
            {
                section = new PasswordSafeSection();
                section.SectionInformation.AllowExeDefinition = ConfigurationAllowExeDefinition.MachineToLocalUser;
                section.SectionInformation.ForceSave = true;
                config.Sections.Add( "passwordSafe", section );
                config.Save( ConfigurationSaveMode.Full );
            }
            return config;
        }
        #endregion
    }

Hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文