用于在主题上实现不同行为的良好设计模式

Kam*_*yar 9 c# architecture design-patterns hierarchy

这种情况的最佳设计是什么?
我有不同的对象类型:User,Channel,MessageBox,UserGroup,等
User,并Channel可以对其他对象的权限.例如User,将以下枚举定义为其权限MessageBox:

CanRead,
CanWrite,
CanDelete,
...
Run Code Online (Sandbox Code Playgroud)

其他枚举被定义为User其他对象类型的所有者.

此外,Channel在这些对象上具有不同的枚举值.例如,考虑Channel作为所有者和MessageBox对象:

CanDispath
CanRetrieve
...
Run Code Online (Sandbox Code Playgroud)

使用按位比较从数据库中的特定表保存和检索所有权限:

OwnerID........OwnerType........ObjectID........ObjectType........AccessLevel  
  1              User              10           MessageBox            38     
  5             Channel            12           MessageBox            18  
Run Code Online (Sandbox Code Playgroud)

现在在代码背后,实现权限类的最佳方法是什么?

1-定义PermissionManager,UserPermissionManager,ChannelPermissionManager分别类彼此.其他类只是调用PermissionManager:

if (new PermissionManager.HasAccess(CurrentUser,  
                                    CurrentMessageBox, 
                                    UserPermissions.CanReadMessages))  
Run Code Online (Sandbox Code Playgroud)

然后PermissionManager根据OwnerType(UserPermissionManagerChannelPermissionManager)决定与之相关的类,并调用其HasAccess方法.这样,PermissionManager.HasAccess总是被调用,我认为它可以使代码更易于维护和扩展.这是我的首选解决方案,但由于PermissionManager,UserPermissionManagerChannelPermissionManager指向同一个背景下,我觉得应该有一个层次或可能是一个接口,因此这3类变得更加一体化.但我不知道如何将它们联系在一起.

2-定义IPermissionManager界面并实现UserPermissionManagerChannelPermissionManager从中实现.添加PermissionManagerTypes枚举.创建一个工厂类并调用管理器,如:

IPermissionManager UserManager =   
    PermissionFactory.Create(PermissionsManagerTypes.User);
if (UserManager.HasAccess(CurrentUser,  
                          CurrentMessageBox, 
                          UserPermissions.CanReadMessages))  
Run Code Online (Sandbox Code Playgroud)

这是一种将类联系在一起的失败尝试.但我认为在这里提一下让你知道我想要实现的目标是件好事.

PS我不能将类定义为静态,因为它们需要具有类型的私有变量 ObjectContext(Entity Framework).

有没有更好的解决方案来实现这一目标?
感谢你和道歉,这是一个非常冗长的问题.

Flo*_*her 3

嗯,这个问题很难回答。您可以尝试创建一个基本接口IPermission;

interface IPermission<TOwner>
{
}
Run Code Online (Sandbox Code Playgroud)

然后,您为您希望能够拥有权限的类型实现此接口。

class UserPermission : IPermission<User>
{
    public UserPermission(CustomerPermissionType type)
    {
        // Store the type
    }
}

class ChannelPermission : IPermission<Channel>
{
    public ChannelPermission (ChannelPermissionType type)
    {
        // Store the type
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您需要一个为特定对象提供权限的接口。

interface IPermissionProvider
{
    bool HasPermission<TOwner>(IPermission<TOwner> permission, TOwner owner, object target);
}
Run Code Online (Sandbox Code Playgroud)

此时,您已经具备了查询权限的基本功能。问题是如何管理用户和通道权限的不同处理。你可以实现这样的事情:

class PermissionDispatcher : IPermissionProvider
{
    public void RegisterPermissionProvider<TOwner>(IPermissionProvider     permissionProvider)
    {
        // Store it somewhere
    }

    public IPermissionProvider GetPermissionProvider<TOwner>()
    {
        // Look up a permission provider that is registered for the specified type TOwner and return it.
    }

    bool IPermissionProvider.HasPermission<TOwner>(IPermission<TOwner> permission,     TOwner owner, object target)
    {
        IPermissionProvider  permissionProvider = GetPermissionProvider<TOwner>();
        return permissionProvider .HasPermission<TOwner>(permission, owner, target);
    }
}
Run Code Online (Sandbox Code Playgroud)

最后一步是为用户和通道创建 IPermissionProvider 的特定实现,并在应用程序/服务启动时将它们注册到 PermissionDispatcher。

用法就像这样简单:

void foo()
{
    IPermissionProvider permissionProvider = ... the dispatcher, could be a singleton ...;
    User user = ...;
    MessageBox messageBox = ...;
    UserPermission userCanReadPermission = new UserPermission(UserPermissionType.CanRead);
    bool hasUserCanReadPermission = permissionProvider.HasPermission(userCanReadPermission, user, messageBox);
Run Code Online (Sandbox Code Playgroud)

}

像这样的事情将是解决这个问题的唯一方法,而不依赖于域类型中的权限处理。尽管如此,我绝对确定这不是完美的解决方案。