【发布时间】:2010-07-08 15:57:59
【问题描述】:
在工作代码中,我们有很多魔术字符串的用法,比如下面的代码 sn-p:
if (user.HasRight("Profile.View")) {...}
所以有很多地方我们传递一个字符串作为参数来查看用户是否有特定的权限。我不喜欢这样,因为这会产生很多魔术字符串。
有什么更好的方法?
枚举、常量、类?
【问题讨论】:
标签: .net magic-string
在工作代码中,我们有很多魔术字符串的用法,比如下面的代码 sn-p:
if (user.HasRight("Profile.View")) {...}
所以有很多地方我们传递一个字符串作为参数来查看用户是否有特定的权限。我不喜欢这样,因为这会产生很多魔术字符串。
有什么更好的方法?
枚举、常量、类?
【问题讨论】:
标签: .net magic-string
在这种特定情况下,请使用枚举。不会有魔术字符串,如果 Enum 发生变化(以一种会破坏魔术字符串解决方案的方式),应用程序将不再编译。
public enum ProfilePermissions
{
View,
Create,
Edit,
Delete
}
那么你可以简单地拥有:
if(user.HasRight(ProfilePermissions.View)) { }
你也可以使用一个类,但是当涉及到更复杂的场景时你会限制自己。例如,将枚举简单更改为:
public enum ProfilePermissions
{
View = 1,
Create = 2,
Edit = 4,
Delete = 8
}
将允许您对更复杂的权限使用按位运算符(例如,用户需要创建或删除的情况):
if(user.HasRight(ProfilePermissions.Create | ProfilePermissions.Delete));
【讨论】:
| 组合值,例如使用值 0x1、0x2、0x4 等...
enum 的目的是创建一个常量的“枚举列表”。将常量分组到可以像这样列出的位置是一个好主意,也可以让程序更有逻辑性。
ProfilePermissions.View.ToString() 来获取字符串“View”,或者如果您需要自定义字符串表示,您可以添加一个装饰 Description此处描述的属性:blogs.msdn.com/b/abhinaba/archive/2005/10/20/483000.aspx
ThirdPartyLibrary.GetResponse(string role) 可以将 enum Roles { Admin, Editor, Guest } 作为 ThirdPartyLibrary.GetResponse(Roles.Guest.ToString()) 代码>
这在 .NET 框架中也很常见。例如 System.Windows.DataFormats 和 System.Net.WebRequestMethods.Http。你想要只读的品种:
public static class MumbleRights {
public static readonly string ProfileView = "Profile.View";
// etc..
}
【讨论】:
扩展方法!将它们放在同一个地方以跟踪所有魔术字符串。
public static class UserRightsExtensions {
public static bool CanReadProfile(this User user)
{
return user.HasRight("Profile.View");
}
// etc..
}
那么你可以:
if (user.CanReadProfile()) .....
【讨论】:
创建一个对这些属性进行强类型化的类,例如
public static class UserInfo
{
public static bool CanViewProfile { get { return User.HasRight("Profile.View"); } }
}
这会将您的“魔术字符串”保留在代码中的一个位置。枚举也可以,但在我看来它不那么可读。
注意:我的示例旨在充当登录用户的属性代理,因此是静态类。如果您想要一些可以处理更直接的数据(例如,用户列表)的东西,那么这种类型的类需要是非静态的,并且需要在每个用户帐户的基础上进行实例化。
【讨论】:
CanViewProfile 在我看来作为静态属性毫无意义,而应该是用户对象上的实例方法。 sn-p 建议每个用户都有一个静态类?
你可以在 C# 中做常量字符串。
您可以像这样在标头中定义所有字符串:
const string PROFILE_VIEW "Profile.View";
不确定这是否是“最佳”方式,但它肯定比在代码中使用魔法值更好。
【讨论】:
我赞同“贾斯汀·尼斯纳”所展示的方式。但在某些情况下,我宁愿编写以下代码结构。
public class User
{
public Permission Permission { get; set; }
}
public abstract class Permission
{
}
public class ViewPermission:Permission
{
}
你可以把它当作
User user=new User();
if(user.Permission is ViewPermission)
{
}
【讨论】: