【问题标题】:Better code/ Pattern for checking existence of value更好的代码/模式来检查价值的存在
【发布时间】:2012-07-31 12:20:01
【问题描述】:

我有如下所示的 web.config 条目。这是为了控制不同角色的用户对不同页面的访问。

招聘经理和 CRM1 可以访问管理屏幕 CRM3和Transferee可以访问日志屏幕

add key="AdminScreenRoles" value ="Hiring Manager,CRM1"
add key="LogsScreenRoles" value ="CRM3,Transferee "

将来可以授予新角色访问管理屏幕的权限。也可能会引入新页面。

我需要确保当前用户至少可以访问配置文件中的一个页面。我有以下代码。有用。此功能是否有更好/简洁/可扩展的代码?

List<string> authorizedRolesForAdmin = new List<string>((ConfigurationManager.AppSettings["AdminScreenRoles"]).Split(','));
List<string> authorizedRolesForLogs = new List<string>((ConfigurationManager.AppSettings["LogsScreenRoles"]).Split(','));
if ((authorizedRolesForAdmin.Contains(roleName)) || (authorizedRolesForLogs.Contains(roleName)))
{
    //Has access to at least one page
}

参考

  1. Scalable C# Code for Creating Array from Config File

【问题讨论】:

  • 这在 web.config 文件中可能会变得非常丑陋,我建议您在数据库表中对此进行建模以获得更大的灵活性。
  • 您可以考虑两件事。 1. 缓存 List 并在添加新角色时清除缓存,2. 使用包含搜索更快的 Dictionary。
  • 或者,如果您的组织使用 Active Directory,请使用 AD 角色/组来管理此信息。
  • @JonH 谢谢。我明白那个。但是这个建议是题外话
  • 这就是为什么我们评论,没有回答。

标签: c# asp.net .net algorithm design-patterns


【解决方案1】:

您绝对可以像这样显着简化现有代码:

var hasOneRole =
    new [] { "Admin", "Log" }
    .SelectMany( screen => ( ConfigurationManager.AppSettings[ screen + "ScreenRoles" ] ?? "" ).Split( ',' ) )
    .Contains( roleName );

但是随着时间的推移,这仍然会变得丑陋。 Web.config 只是不适合那种东西。我建议您将访问控制设置放入数据库中。

【讨论】:

  • 谢谢..这符合我目前的需要。
  • 我还建议通过添加 ?? "" 来防止 AppSettings[] 返回 null。
  • @FyodorSoikin 我通常会避免这样做以明确导致错误丢失。我宁愿让网站关闭,然后在无效状态下混日子。
  • @asawyer:虽然这一点是正确的,但它不适用于这种情况。当缺少角色列表时,您希望将其视为空列表。此外,如果您确实希望产生错误,则最好明确检查此条件并产生有意义的错误,而不是生成通用 NRE。大大简化了调试。
  • @FyodorSoikin 在这种特殊情况下,读取 lambda 之外的应用程序设置(至少对我而言)更有意义,这样您就可以进行这种检查和抛出。然而,有了它 inside lambda,如果丢失,我会让它抛出。
【解决方案2】:

如果不是一些建议的话,这里没有太多空间可以让事情变得更好,例如:

如果角色列表的数量变大

  • 使用Dictionary&lt;RoleName..&gt;HashSet

可能是你可以控制喜欢的存在,避免创建额外的List&lt;T&gt; 实例

(ConfigurationManager.AppSettings["AdminScreenRoles"]).
              Contains("roleName,")//tiny optimization....

但正如我之前所说,现在看起来的代码是最好的,因为它易于理解和阅读。

【讨论】:

    【解决方案3】:

    你可以避免拆分字符串,而是使用这样的东西,这应该会稍微快一些:

    string authorizedRolesForAdmin = string.Concat(",", ConfigurationManager.AppSettings["AdminScreenRoles"]), ",");
    string authorizedRolesForLogs = string.Concat(",", ConfigurationManager.AppSettings["LogsScreenRoles"]), ",");
    string searchString = string.Concat(",", roleName, ",");
    
        if ((authorizedRolesForAdmin.Contains(roleName)) || (authorizedRolesForLogs.Contains(roleName)))
        {
            //Has access to at least one page
        }
    

    这避免了比较昂贵的 string.Split,也避免了创建两个列表。值得注意的是,string.Contains 仅是 .NET4;在旧版本中,您将改为检查 string.IndexOf 的值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-24
      • 2016-06-27
      • 2013-02-19
      • 2012-08-10
      • 1970-01-01
      相关资源
      最近更新 更多