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

Posted

技术标签:

【中文标题】在我自己的自定义 appSettings 上使用 foreach 所需的代码【英文标题】:Code required to use foreach on my own custom appSettings 【发布时间】:2011-02-03 20:05:23 【问题描述】:

我已经搜索了该网站,但没有找到我正在寻找的确切内容。关闭,但没有雪茄。

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

<configSections>
    <section name="PhoneNotificationsSection" type="Alerts.PhoneAlertConfigSection,Alerts,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/>    
</configSections>
<PhoneNotificationsSection>
  <phones>
    <add phone="MyMobile" value="1234567890@vtext.com" />
    <add phone="OtherMobile" value="1234567890@txt.att.com" />
  </phones>
</PhoneNotificationsSection>

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

foreach (phone p in phones)

   //'phone' attribute is just helpful/descriptive
   DoSomething(p.value);

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

【问题讨论】:

【参考方案1】:

我曾经写过类似的东西,作为 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>

为了匹配上面的 sn-p 我们首先需要配置部分:

    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
    

现在,一切就绪,我们就可以访问配置文件了。我正在使用一个 Configurator 帮助类来简化这个过程:

    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
    

希望这会有所帮助。

【讨论】:

无法编译此代码 - 最后一个代码 sn-p 中返回“SystemConfiguration”对象的最后 2 个方法 - 编译器无法识别 SystemConfiguration 类并认为我缺少程序集参考。该类在哪里定义?我需要特定的“使用”声明吗? 另外 - 你能告诉我你如何使用这个代码来访问 循环/语句中的元素吗?到目前为止我尝试过的是返回一个空的 ElementCollection 没关系,我让它工作了 - 只需将“SystemConfiguration”的所有实例更改为“Configuration”。谢谢! 很高兴你解决了。如果您遇到另一个障碍,请告诉我。 SystemConfiguration的类型是什么?

以上是关于在我自己的自定义 appSettings 上使用 foreach 所需的代码的主要内容,如果未能解决你的问题,请参考以下文章

如何在我自己的自定义视图中重现 iPhone UIScrollView 的轻弹滚动行为?

如何使用 Tensorflow 2 在我的自定义优化器上更新可训练变量

Qt Creator IDE 中的自定义字体

无法让我的自定义播放按钮在我的视频播放器上工作

Drupal 视图模块卡在我的自定义主题上

docker 容器上 Parse-server 的自定义身份验证 (OAuth2)