当前位置:  开发笔记 > 编程语言 > 正文

使用f#时,如何在Api控制器中为每个新方法触摸我的DI容器

如何解决《使用f#时,如何在Api控制器中为每个新方法触摸我的DI容器》经验,为你挑选了1个好方法。

当我使用像Ninject这样的WebApi时,我试图围绕如何处理F#中的DI.

例如,在C#中,当我连接我的容器时,我只是告诉DI类型解析的内容,例如:

kernel.Bind().To();

当控制器构造函数需要时,我的Api控制器将自动连接它.

太棒了,现在我可以整天为接口和类添加方法,无需再次触摸容器.

但是在F#中(除非我这样做完全错误)我创建了部分应用程序然后将它们传递给控制器​​,每次我添加一个方法我必须再次在容器中连接.也许这是正确的,我不确定,但似乎更多的接线.

为了澄清我的意思,让我们来看一个典型的REST Api.对于每个具有CRUD的实体 - 例如:

客户(创建,读取,更新,删除).

那么我是否必须将每个功能注入控制器?

所以在这个例子中,假设我有服务 - >域 - > repo模型:

let createCustomerFunc = createCustomerDomainFunc createCustomerRepoFunc
let getAllCustomersFunc = getAllCustomerDomainFunc getAllCustomerRepoFunc
let updateCustomerFunc cust = [...]
let deleteCustomerFunc id = [...]
let getSingleCustomerFunc id = [...]

现在在我的容器中,当我绑定它时,我会做类似的事情:

kernel.Bind().To()
.WithConstructorArgument(createCustomerFunc, getAllCustomerFunc, etc...) 
|> ignore

现在如果我添加方法:GetActiveCustomers我将不得不修改上面的代码以传递新的部分应用程序?

感觉......错了 - 我只是错误地接近这个?



1> Mark Seemann..:

使用DI容器提供了一些优点,以及一些缺点.

主要优点是,如果您有一个庞大的代码库,您可以使用约定优于配置来连接所有依赖项.使用约定优于配置,您还可以获得代码必须更加一致的好处,因为它必须遵循约定.

但是有几个缺点.最直接的是你失去了编译器的快速反馈.您可以更轻松地对系统进行更改,并且在编译所有内容时,系统会在运行时失败.有些人希望你可以要求DI容器进行自我诊断,但你不能.

使用DI容器的另一个不那么明显的缺点是,如你所说,简单地向控制器等添加更多成员就太容易了.这实际上增加了耦合,或降低了内聚力,但DI提供的基于反射的自动化容器隐藏了这个问题.

由于我认为缺点超过了优点,我建议您使用Pure DI而不是DI Containers.

这适用于C#,Visual Basic .NET或Java中的面向对象编程,但同样适用于F#中的函数编程.

在未混合的Functional F#代码库中,我根本不会使用类或接口; 相反,我只会把功能组合在一起.

在使用ASP.NET Web API的混合代码库中,我尽可能快地跨越OOP和FP之间的桥梁.正如我在使用F# talk的测试驱动开发中解释的那样(在Pluralsight上可用的扩展材料),我将一个函数注入到Controller中,如下所示:

type ReservationsController(imp) =
    inherit ApiController()
    member this.Post(rendition : ReservationRendition) : IHttpActionResult =
        match imp rendition with
        | Failure(ValidationError msg) -> this.BadRequest msg :> _
        | Failure CapacityExceeded -> this.StatusCode HttpStatusCode.Forbidden :> _
        | Success () -> this.Ok () :> _

这是该控制器的整个代码库.所有行为都是通过实现的imp.

在应用程序的启动代码中,imp组成如下:

let imp =
    Validate.reservationValid
    >> Rop.bind (Capacity.check 10 SqlGateway.getReservedSeats)
    >> Rop.map SqlGateway.saveReservation

您可能会争辩说上面ReservationsController只定义了一种Post方法.如果Controller必须公开更多方法怎么办?

在这种情况下,为每个方法注入一个实现函数.在REST API中,任何Controller都应该只有2-3个方法,这实际上意味着2-3个依赖项.在我看来,这是一个完全可以接受的依赖项数量.


2-3方法最大的原因是在适当的RESTful设计中,资源往往遵循一些交互模式:

GET

POST

POST, GET

PUT, GET

DELETE, GET

PUT,DELETE,GET

完整的组合(POST,GET,PUT,DELETE)是一个REST设计的味道,但所有的是一个完全不同的讨论.

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有