2010-10-09 74 views
1
public partial class MembershipModule : BaseEntity<MembershipModule> 
{ 
    /// <summary> 
    /// Returns wheter a module is accessible 
    /// </summary> 
    public static bool IsAccessible(MembershipModule module) 
    { 
     // In absence of a module, no security applies to the page 
     if(module == null) 
      return true; 

     return module.IsAccessible(); 
    } 

    /// <summary> 
    /// Returns whether the module is accessible 
    /// </summary> 
    /// <returns></returns> 
    public bool IsAccessible() 
    { 
     // Skip unnecessary querying 
     if(!MembershipUser.Connected) 
      return this.Enabled && this.OfflineAccess; 

     Guid accessGuid = MembershipAction.AccessGuid; 

     // ModuleActions for this MembershipModule and the Access Action 
     IQueryable<MembershipModuleAction> accessMA = 
      from ma in LinqUtil.Context.MembershipModuleActions 
      where ma.ModuleId.Equals(this.Id) && ma.ActionId.Equals(accessGuid) 
      select ma; 

     // RolePrivileges that grant access on this MembershipModule for the Current MembershipUser 
     IQueryable<bool> accessRP = 
      from rp in LinqUtil.Context.MembershipRolePrivileges 
      where accessMA.Contains(rp.MembershipModuleAction) 
      select rp.MembershipRole.MembershipUsers.Contains(MembershipUser.Current); 

     return this.Enabled && (this.OfflineAccess || accessRP.ToList().FirstOrDefault()); 
    } 

    /// <summary> 
    /// Returns all accessible modules that can be accessed by the logged user 
    /// </summary> 
    /// <returns></returns> 
    public static IEnumerable<MembershipModule> GetAccesible() 
    { 
     // Skip unnecessary querying 
     if(!MembershipUser.Connected) 
      return LinqUtil.Context.MembershipModules.Where(m => m.Enabled && m.OfflineAccess).ToList(); 

     Guid accessGuid = MembershipAction.AccessGuid; 

     // ModuleActions for any MembershipModule with the Access Action 
     IQueryable<MembershipModuleAction> accessMA = 
      from ma in LinqUtil.Context.MembershipModuleActions 
      where LinqUtil.Context.MembershipModules.Any(m => m.Enabled && m.Id.Equals(ma.ModuleId)) && ma.ActionId.Equals(accessGuid) 
      select ma; 

     // RolePrivileges that grant access on those MembershipModule for the Current MembershipUser 
     IQueryable<MembershipRolePrivilege> accessRP = 
      from rp in LinqUtil.Context.MembershipRolePrivileges 
      where accessMA.Any(ma => rp.MembershipModuleAction.Id.Equals(ma.Id)) && rp.MembershipRole.MembershipUsers.Any(u => u.Id.Equals(MembershipUser.Current.Id)) 
      select rp; 

     // Accessible modules 
     var modules = 
      from m in LinqUtil.Context.MembershipModules 
      where accessMA.Any(ma => ma.MembershipModule.Id.Equals(m.Id)) && accessRP.Any(rp => rp.MembershipModuleAction.ModuleId.Equals(m.Id)) 
      select m; 

     return modules.ToList(); 
    } 

    /// <summary> 
    /// Menu Items that can be displayed on the current web page 
    /// </summary> 
    public static IEnumerable<MembershipModule> GetMenuItems(string uriPrefix) 
    { 
     IEnumerable<MembershipModule> list = GetAccesible(); 

     return list.Where(m => m.UriPrefix.Equals(uriPrefix) && m.MenuItem).OrderBy(m => m.Position); 
    } 
} 

這個當前工作,但由於某些原因,我不禁聯想到的代碼看起來醜陋(尤其是兩個非常相似的靜態和實例函數,讓我的訪問頁面簡化過於複雜的LINQ查詢 - 查詢

如何重構這個有什麼想法看起來更吸引人

獎金的問題:

Guid accessGuid = MembershipAction.AccessGuid; 

不使用該行,而只是調用我的查詢MembershipAction.AccessGuid,我得到一個錯誤,告訴我一些晦澀:

類成員 MembershipAction.AccessGuid是 未映射。

棘手的部分來了:在靜態GetAccessible()函數這不會發生。我可以將MembershipAction.AccessGuid添加到查詢中,但它在實例IsAccessible()函數中出現此問題。

爲了記錄在案,這裏的MembershipAction:

public partial class MembershipAction : BaseEntity<MembershipAction> 
{ 
    public const string AccessPrivilege = "Access"; 

    private static Guid accessGuid = Guid.Empty; 
    public static Guid AccessGuid 
    { 
     get 
     { 
      if(accessGuid == Guid.Empty) 
      { 
       IQueryable<Guid> query = from a in LinqUtil.Context.MembershipActions 
             where a.Name.Equals(AccessPrivilege) 
             select a.Id; 

       accessGuid = query.ToList().FirstOrDefault(); 
      } 

      return accessGuid; 
     } 
    } 
} 
+0

嗯,你可以肯定的因素'accessMA'和'accessRP'到它自己的方法,他們都呼籲,甚至到其自己的領域,因爲它還是要用延遲執行您在創建設置。 – 2010-10-09 20:31:22

+0

@Kirk Woll:訪問MA的查詢在IsAccessible和GetAccessible中不一樣(對於accessRP也一樣)。 – 2010-10-09 21:38:26

回答

0

一提的是,這是個人意見,我們都在這裏他們有云:

  1. 在查詢內溝通使用lambda表達式。選擇一種風格,並使用它的傢伙。
  2. 擺脫where子句中的&符號。你可以用另一行從where開始獲得相同的結果。
  3. 不要害怕查詢另一個查詢。如果它更容易理解,沒有理由不這樣做。編譯器會將它們合併爲一個查詢。
  4. 許多人會指出,靜態方法通常指向代碼味道。爲什麼你需要靜態和實例方法?也許班上的一些清晰度是有條理的。
0

是不是很簡單:

public static IEnumerable<MembershipModule> GetAccesible() 
{ 
    // Skip unnecessary querying 
    if(!MembershipUser.Connected) 
     return LinqUtil.Context.MembershipModules.Where(m => m.Enabled && m.OfflineAccess).ToList(); 

    // Accessible modules 
    var modules = 
     from m in LinqUtil.Context.MembershipModules 
     where m.IsAccessible() 
     select m; 

    return modules.ToList(); 
}