C# Рефакторинг - Как передать метод generi c с несколькими параметрами? - PullRequest
0 голосов
/ 07 января 2020

У меня есть классы бизнес-объектов с несколькими методами, которые обычно следуют шаблону:

  • всегда возвращают объект Результат
  • тестирует логическое предварительное условие: IsAllowed (для проверки, например, если кто-то может что-то сделать (перечисление MyAction) в данном контексте (перечисление MyContext).
  • если тест пройден, то сделать что-то (обычно на уровне базы данных, возвращающем объект Result), в противном случае вернуть PermissionDenied (), который возвращает Результат (простой объект с логическим результатом, установленным как false, и другие свойства, включая сообщения об ошибках).

Пример:

protected MyContext Context;
protected MyAction Action;

public Result List1(int p1, int p2, int p3, object p4, string p5)
    => IsAllowed(MyContext.Page, MyAction.List) ? DB.List1(p1, p2, p3, p4, p5) : PermissionDenied();

public Result View2(int p1, int p2)
    => IsAllowed(this.Context, this.Action) ? DB.View2(p1, p2) : PermissionDenied();

public Result Edit3(int p1, string p2)
    => IsAllowed(MyContext.Document, MyAction.Edit) ? DB.Edit3(p1, p2) : PermissionDenied();

(...)

Мне бы хотелось узнать, как чтобы улучшить и упростить этот шаблон , имея метод, который может обрабатывать это условие предоставления. Я представляю что-то вроде GrantDo () , но как этот метод может обрабатывать / получать внутренний метод, представленный здесь как ??? what

Public Result GrantDo(??? what, MyContext? ctx=null, MyAction? act=null){
    if (IsAllowed(ctx == null ? this.Context : ctx, act == null ? this.Action : act))
        return what();    
    else
        return PermissionDenied();
}

Таким образом, я думаю, что вышеприведенные методы можно переписать так:

public Result List1(int p1, int p2, int p3, object p4, string p5)
    => GrantDo(DB.List1(p1, p2, p3, p4, p5), MyContext.Page, MyAction.List);

public Result View2(int p1, int p2) => GrantDo(DB.View2(p1, p2));

(...)

Than К вам за любые предложения и идеи.

Ответы [ 2 ]

1 голос
/ 08 января 2020

Я наконец получил это рабочее решение (спасибо за ваше руководство @Alvin).

public Result GrantDo(Func<Result> method, MyAction action, MyContext? context = null)
=> IsAllowed(context ?? Context, action) ? method() : PermissionDenied();

Найдена дополнительная информация о различных понятиях:

Действие - это делегат (указатель) на метод, который принимает ноль, один или несколько входных параметров, но ничего не возвращает.

Fun c является делегатом (указателем) метода, который принимает ноль, один или несколько входных параметров и возвращает значение (или ссылку) .

Предикат - это особый вид Fun c, часто используемый для сравнений.

source: Fun c против Action против Предикат

1 голос
/ 07 января 2020

Вам просто нужно передать функцию ( Действие Веселье c), и вы можете упростить нулевые проверки:

public Result GrantDo(Func<Result> action, MyContext? ctx = null, MyAction? act = null) =>
    IsAllowed(context ?? this.Context, act ?? this.Action) 
        ? action() 
        : PermissionDenied();
...