【问题标题】:Code required to use foreach on my own custom appSettings在我自己的自定义 appSettings 上使用 foreach 所需的代码
【发布时间】: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 配置世界时,我的大脑开始受到伤害。任何人都可以分享一些我正在寻找的代码吗?

【问题讨论】:

    标签: configuration app-config configuration-files config appsettings


    【解决方案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的类型是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多