элегантное решение проблемы с шаблонами проектирования C # - PullRequest
3 голосов
/ 22 августа 2011

У меня проблема.

Мне нужно найти способ динамически создавать экземпляры классов и динамически активировать методы в этих классах в соответствии с некоторыми разрешениями пользователя, а также группировать, что пользователь может запросить.

например:

1.разрешение пользователя «A»

вызов классов 1,4,6

вызов методов 2,7 в классе 1.

вызов методов 1,2 в классе 4.

вызывает методы 1,2 в классе 6.

2.разрешение пользователя "B"

вызов классов 2,3,5

вызов метода 2,7 в классе 2.

вызов метода 1,2 в классе 3.

вызовите метод 1,2 в классе 5.

Я сделал эти примеры только с разными разрешениями.но он также может содержать группировку, что означает, что для каждого разрешения можно вызывать разные классы и разные методы (своего рода подмножество).

я могу делать все с помощью switch / case, но я ищу болееэлегантный способ сделать это.

Примечания:

  1. существует множество возможностей из-за множества классов-методов из-за множества различных типов группировки, которые пользователь может задатьfor.

  2. Я не знаю точно, как лучше всего передать разрешения.

  3. Я думал, что, возможно, шаблон команды илитут может помочь декоратор.

Большое спасибо за ваши ответы!

Ответы [ 4 ]

3 голосов
/ 22 августа 2011

Предполагая, что у вас есть доступ к классам, можно использовать прокси-классы и атрибуты:

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);
    }
}

Если вместо создания прокси вручную вы использовали динамический генератор прокси, который перехватывал все методы, вы могли бы явно выполнить проверку разрешений без необходимости вручную писать много шаблонного кода.

0 голосов
/ 22 августа 2011

Вы можете привязать строки к вызовам классов и методов, используя Func <>. Это дает вам большую гибкость в управлении многими перестановками, с которыми вы имеете дело. У меня есть пример кода ниже, но вы можете использовать Enums вместо строк для ключа.

Это не обязательно шаблон, но его можно использовать с несколькими из упомянутых шаблонов.

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;
        }
    }
0 голосов
/ 22 августа 2011

Вы также можете посмотреть на Factory Pattern .

0 голосов
/ 22 августа 2011

Звучит так, будто вы ищете что-то похожее на CodeAccessPermissionAttribute - подробности см. здесь .Возможно, я бы порекомендовал шаблон, похожий на этот;Определите объекты с атрибутами, чтобы связать их состояния разрешений, и тогда ваши пользователи попадут в роли, которые имеют или не имеют разрешения на выполнение методов с определенными атрибутами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...