【问题标题】:C# Refactoring - How to pass generic method with possibly multiple parameters?C# 重构 - 如何传递可能有多个参数的泛型方法?
【发布时间】:2023-04-08 07:16:02
【问题描述】:

我的业务对象类有几个通常遵循该模式的方法:

  • 总是返回一个对象结果
  • 测试一个布尔前置条件:IsAllowed(例如检查某人是否可以在给定的上下文(MyContext 枚举)中做某事(MyAction 枚举)。
  • 如果测试通过,则执行某些操作(通常在数据库级别返回一个 Result 对象),否则返回 PermissionDenied(),它返回一个 Result(一个简单的对象,其布尔结果集为 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() 这样的东西,但是该方法如何处理/接收内部方法,这里表示为 ?什么

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

(...)

感谢您的任何建议和想法。

【问题讨论】:

  • 你可以为每个参数使用generic of T。例如,看看Dictionary 是如何实现的 -> referencesource.microsoft.com/#mscorlib/system/collections/… 你可以设置像 T 这将是你的 int 和 E 这将是你的对象和重载方法来满足你的需要。
  • 这些是相当大的函数签名。考虑是否应该将参数重构为一个类。

标签: c# generics methods refactoring


【解决方案1】:

我终于得到了这个可行的解决方案(感谢您的指导@Alvin)。

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

找到有关不同概念的更多信息:

Action 是一个方法的委托(指针),它接受零个、一个或多个输入参数,但不返回任何内容。

Func 是一个方法的委托(指针),它接受零个、一个或多个输入参数,并返回一个值(或引用)。

谓词是一种特殊的 Func,常用于比较。

来源:Func vs. Action vs. Predicate

【讨论】:

    【解决方案2】:

    您只需要传递一个函数(an Action a Func)就可以简化空检查:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-08
      • 2021-10-21
      • 1970-01-01
      相关资源
      最近更新 更多