用c#设计模式优雅地解决了一个问题
本文关键字:问题 一个 解决 设计模式 | 更新日期: 2023-09-27 18:06:33
我有一个问题。
我需要找到一种方法来动态实例化类和动态激活这些类中的方法,根据一些用户权限和用户可以请求的分组。
例如:
1。用户权限A
调用类1、4、6
在类1中调用方法2,7
调用类4中的方法1,2。
调用类6中的方法1,2。
2。用户权限"B"
调用类2、3、5
在类2中调用方法2,7
在类3中调用方法1,2。
在类5中调用方法1,2
我只在不同的权限下做了这些例子。但是它也可以包含分组,这意味着可以为每个权限调用不同的类和不同的方法(某种子集)。
我可以用switch/case做所有的事情,但是我正在寻找一种更优雅的方法。
指出:
-
有很多可能性,因为有很多类方法,因为有很多不同类型的分组,用户可以请求
-
我不知道通过权限的最佳方式是什么
-
我想也许命令模式或装饰符可以帮助这里
非常感谢你的回答!
假设您可以访问这些类,一种方法是使用代理类和属性:
class PermissionVerifier {
public void ExecuteIfHasPermission(Permission perm, Action action) {
if (GetCurrentUser().HasPermission(perm)) // assumes singleton-like
// access or injected user
action();
throw CreatePermissionException(perm);
}
}
class A {
// make it obvious what permissions are required for execution
[RequiresPermission(Permissions.CanExecuteClassAMethod1)]
public virtual void Method1() {
//...
}
}
class AProxy: A {
private PermissionVerifier verifier;
public override void Method1() {
ExecuteIfHasPermission(
GetCurrentMethodRequiresPermissionAttribute(), // reflection
() => base.Method1());
}
private ExecuteIfHasPermission(Permission perm, Action action) {
verifier.ExecuteIfHasPermission(perm, action);
}
}
如果不是手动创建代理,而是使用拦截所有方法的动态代理生成器,则可以显式执行权限检查,而无需手动编写大量样板代码。
听起来您正在寻找类似于CodeAccessPermissionAttribute
的东西-请参阅此处了解详细信息。我可能会推荐一个类似的模式;定义带有属性的对象来关联它们的权限状态,然后你的用户就会归属于有或没有权限执行带有特定属性的方法的角色。
您还可以查看工厂模式
可以使用Func<>将字符串绑定到类和方法调用。它使您在处理您正在处理的许多排列时具有很大的灵活性。我下面有一个代码示例,但是您可以使用枚举而不是字符串作为键。
这不一定是一个模式,但它可以与前面提到的几个模式一起使用。
public void Call(Stream str)
{
//Single Permission
Generate["PermissionA"](str);
//Say this user has multiple permissions, you can iterate over them
IEnumerable<string> userPerms = GetUserPerms();
foreach (var perm in userPerms)
{
Generate[perm](str);
}
}
public static Dictionary<string, Func<Stream, object>> Generate
{
get
{
var ret = new Dictionary<string, Func<Stream, object>>();
ret.Add("PermissionA", (s) =>
{
Class1 cl1 = new Class1(s);
Class4 cl4 = new Class4(s);
Class6 cl6 = new Class6(s);
cl1.Method2();
cl1.Method7();
cl4.Method1();
cl4.Method2();
cl6.Method1();
cl6.Method2();
cl1.DoXml();
cl4.DoXml();
cl6.DoXml();
return "";
});
ret.Add("PermissionB", (s) =>
{
Class2 cl2 = new Class2(s);
Class3 cl3 = new Class3(s);
Class5 cl5 = new Class5(s);
cl2.Method2();
cl2.Method7();
cl3.Method1();
cl3.Method2();
cl5.Method1();
cl5.Method2();
cl2.DoXml();
cl3.DoXml();
cl5.DoXml();
return "";
});
return ret;
}
}