乐趣区

关于.net:如何在-ASPNET-Core-中写出更干净的-Controller

你能够遵循一些最佳实际来写出更洁净的 Controller,个别咱们称这种办法写进去的 Controller 为瘦 Controller,瘦 Controller 的益处在于领有更少的代码,更加繁多的职责,也便于浏览和保护,而且随着工夫的推移也容易做 Controller 的多版本。

这篇文章咱们一起探讨那些让 Controler 变胖变臃肿的一些坏滋味,并且一起摸索让 Controller 变瘦的伎俩,尽管我的一些在 Controller 上的最佳实际可能不是业余的,但我每一步都提供相干源代码来进行优化,接下来的章节中,咱们会探讨什么是 胖 Controller,什么是 坏滋味 ,什么是 瘦 Controller,它能带给咱们什么福利?并且如何让 Controller 变瘦,变简略,利测试,易保护。

从 Controller 中移除数据层代码

当在写 Controller 的时候,你应该恪守 繁多职责,也就意味着你的 Controller 只需做一件事件,换句话说,只有一个因素或者惟一一个因素能让你批改 Controller 中的代码,如果有点懵的话,思考上面的代码片段,它将 数据拜访代码 糅进了 Controller。


public class AuthorController : Controller
{private AuthorContext dataContext = new AuthorContext();
    public ActionResult Index(int authorId)
    {
        var authors = dataContext.Authors
            .OrderByDescending(x=>x.JoiningDate)
            .Where(x=>x.AuthorId == authorId)
            .ToList();
        return View(authors);
    }
    //Other action methods
}

请留神下面的代码在 Action 中应用了 dataContext 从数据库读取数据,这就违反了繁多职责准则,并间接导致了 Controller 的臃肿。

如果后续你须要批改 数据拜访层 代码,可能基于更好的性能或者你能想到的起因,这时候只能被迫在 Controller 中批改,举个例子吧:如果你想把下面的 EF 改成 Dapper 去拜访底层的 Database,更好的做法应该是独自拎进去一个 repository 类来操控 数据拜访 相干的代码,上面是更新后的 AuthorController。


public class AuthorController : Controller
{private AuthorRepository authorRepository = new AuthorRepository();
    public ActionResult Index(int authorId)
    {var authors = authorRepository.GetAuthor(authorId);
        return View(authors);
    }
    //Other action methods
}

当初 AuthorController 看起来是不是精简多了,下面的代码是不是就是最佳实际呢?不齐全是,为什么这么说呢?下面这种写法导致 Controller 变成了 数据拜访组件 ,取出数据后必然少不了一些业务逻辑解决,这就让 Controller 违反了 繁多职责 ,对吧,更通用的做法应该是将 数据拜访逻辑 封装在一个 service 层,上面是优化之后的 AuthorController 类。


public class AuthorController : Controller
{private AuthorService authorService = new AuthorService();
    public ActionResult Index(int authorId)
    {var authors = authorService.GetAuthor(authorId);
        return View(authors);
    }
    //Other action methods
}

再看一下 AuthorService 类,能够看到它利用了 AuthorRepository 去做 CURD 操作。


public class AuthorService
{private AuthorRepository authorRepository = new AuthorRepository();
    public Author GetAuthor (int authorId)
    {return authorRepository.GetAuthor(authorId);
    }
    //Other methods
}

防止写大量代码做对象之间映射

在 DDD 开发中,常常会存在 DTO 和 Domain 对象,在数据 Input 和 Output 的过程中会存在这两个对象之间的 mapping,依照一般的写法大略就是这样的。


public IActionResult GetAuthor(int authorId)
{var author = authorService.GetAuthor(authorId);
    var authorDTO = new AuthorDTO();
    authorDTO.AuthorId = author.AuthorId;
    authorDTO.FirstName = author.FirstName;
    authorDTO.LastName = author.LastName;
    authorDTO.JoiningDate = author.JoiningDate;
    //Other code
   ......
}

能够看到,这种一一映射的写法让 Controller 即时收缩,同时也让 Controller 减少了额定的性能,那如何把这种 模板式 代码躲避掉呢?能够应用业余的 对象映射框架 AutoMapper 去解决,上面的代码展现了如何做 AutoMapper 的配置。


public class AutoMapping
{public static void Initialize()
    {
        Mapper.Initialize(cfg =>
        {cfg.CreateMap<Author, AuthorDTO>();
            //Other code            
        });
    }
}

接下来能够在 Global.asax 中调用 Initialize() 初始化,如下代码所示:


protected void Application_Start()
{AutoMapping.Initialize();         
}

最初,能够将 mapping 逻辑放在 service 层中,请留神上面的代码是如何应用 AutoMapper 实现两个不兼容对象之间的映射。


public class AuthorService
{private AuthorRepository authorRepository = new AuthorRepository();
    public AuthorDTO GetAuthor (int authorId)
    {var author = authorRepository.GetAuthor(authorId);
        return Mapper.Map<AuthorDTO>(author);
    }
    //Other methods
}

防止在 Controller 中写业务逻辑

尽量避免在 Controller 中写 业务逻辑 或者 验证逻辑,Controller 中应该仅仅是接管一个申请,而后被下一个 action 执行,别无其它,回到方才的问题,这两种逻辑该怎么解决呢?

  • 业务逻辑

这些逻辑能够封装 XXXService 类中,比方之前创立的 AuthorService。

  • 验证逻辑

这些逻辑能够用 AOP 的操作手法,比方将其塞入到 Request Pipeline 中解决。

应用依赖注入而不是硬组合

举荐在 Controller 中应用依赖注入的形式来实现对象之间的治理,依赖注入是 管制反转 的一个子集,它通过内部注入对象之间的依赖从而解决外部对象之间的依赖,很拗口是吧!

一旦你用了依赖注入形式,就不须要关怀对象是怎么实例化的,怎么初始化的,上面的代码展现了如何在 AuthorController 下的构造函数中实现 IAuthorService 对象的注入。


public class AuthorController : Controller
{private IAuthorService authorService = new AuthorService();
    public AuthorController(IAuthorService authorService)
    {this.authorService = authorService;}
   // Action methods
}

应用 action filer 打消 Controller 中的反复代码

能够利用 action filter 在 Request pipeline 这个管道的某些点上安插一些你的自定义代码,举个例子,能够应用 ActionFilter 在 Action 的执行前后安插一些自定义代码,而不是将这些业务逻辑放到 Controller 中,让 Controller 不必要的收缩,上面的代码展现了如何去实现。


[ValidateModelState]
[HttpPost]
public ActionResult Create(AuthorRequest request)
{AuthorService authorService = new AuthorService();
    authorService.Save(request);
    return RedirectToAction("Home");
}

总的来说,如果一个 Controller 被赋予了几个职责,那么只有是其中任何一个职责的起因,你都必须对 Controller 进行批改,总的来说,肯定要坚守 繁多准则

译文链接:https://www.infoworld.com/art…

退出移动版