这里有一些接口IOrderSender
,它定义了具有某些实现KafkaOrderSender
的业务操作(订单发送)(通过本示例中的Kafka生产者)。
在保留原始OOP样式的情况下,代码是从C#重写的:
type CustomerId = string
type IOrderSender =
abstract SendOrders: CustomerId -> Order list -> unit
type KafkaOrderSender(config: IConfiguration) =
let streamConfig = config.GetSection("OrderStream")
let producerConfig = new ProducerConfig(BootstrapServers = streamConfig.GetValue("BootstrapServers"))
let producer = new Producer<string, string>(producerConfig)
let ordersTopic: string = streamConfig.GetValue("Topic")
interface IOrderSender with
member this.SendOrders customerId orders =
for order in orders do
let orderJson = JsonConvert.SerializeObject<Order>(order)
let msg = new Message<string, string>(Key = customerId, Value = orderJson)
do producer.BeginProduce(ordersTopic, msg)
interface IDisposable with
member this.Dispose() =
do producer.Flush(CancellationToken.None)
do producer.Dispose()
这里有:
界面(IOrderSender
)
实现(KafkaOrderSender
)
一个外部依赖项(IConfiguration
)
内部状态(producer
,需要在调用之间共享)
状态需要关闭/处理(IDisposable
)
此接口和实现已在某些DI容器中注册(例如带有Giraffe的ASP.NET Core):
let configureServices (services : IServiceCollection) =
services.AddGiraffe() |> ignore
services.AddSingleton<IOrderSender, KafkaOrderSender>() |> ignore
然后通过DI解析此对象并在应用程序逻辑中使用:
let handleOrders (customerId: CustomerId) (orders: Orders): HttpHandler =
fun (next : HttpFunc) (ctx : HttpContext) ->
// Resolve
let orderSender = ctx.GetService<IOrderSender>()
// Use
do orderSender.SendOrders customerId orders
return! text "OK" next ctx
是否有更好的方法以一种更惯用的功能方式(模块代替类,部分应用程序代替通过构造函数的依赖关系)实现IOrderSender?
在这种情况下,如何处理共享状态(生产者)以及如何实现共享状态的处置?