在(ServiceStack)ServiceA中“共享”/解析(ServiceStack)ServiceB是一个坏主意吗
本文关键字:ServiceStack 一个 ServiceA 共享 解析 ServiceB | 更新日期: 2023-09-27 18:34:41
在我们的代码库中,我看到了不同ServiceStack服务之间的一些共享(我认为不合适(。我认为这不是一个好主意,因为每个服务的"边界"变得复杂。例如,通过"边界",它可以表示数据库连接的边界,我将使用数据库连接边界作为示例来说明我的意思。
例如,如果我有以下两个服务。
[Route("/service-a/", Verbs = "POST")]
public class DtoServiceA : IReturn<IList<string>>
{
}
public class ServiceA : Service //service stack service
{
public ServiceA(Funq.Container container) : base(container)
{
_container = container; //I didn't type the full code
}
public IList<string> Post(DtoServiceA request)
{
//do something that belongs to ServiceA
//then resolve ServiceB and call Post() from ServiceB
Container.Resolve<ServiceB>().Post(new DtoServiceB());
return new List<string>();
}
}
[Route("/service-b/", Verbs = "POST")]
public class DtoServiceB : IReturn<IList<string>>
{
}
public class ServiceB : Service //service stack service
{
public ServiceB(Funq.Container container) : base(container)
{
_container = container; //I didn't type the full code
}
public IList<string> Post(DtoServiceB request)
{
//do something that belongs to ServiceB
return new List<string>();
}
}
假设如果我像这样在 Post 方法中控制数据库连接
public IList<string> Post(DtoServiceA request)
{
//suppose if I control db connection like so
using (var conn = IDbConnectionFactory.Open())
{
//do something that belongs to ServiceA
//then resolve ServiceB and call Post() from ServiceB
Container.Resolve<ServiceB>().Post(new DtoServiceB());
//above line will fail because connection has already been opend by ServiecA.Post()
}
}
public IList<string> Post(DtoServiceB request)
{
//suppose if I control db connection like so
using (var conn = IDbConnectionFactory.Open())
{
}
}
因为数据库连接已经打开,所以显然这不是"共享"服务的好方法。但是我们有一种更复杂的方法来打开数据库连接,基本上它会计数/检测它是否打开,因此不会多次打开连接。但这对我来说是代码气味。
我在其他地方已经有人建议以类似的方式共享服务。我不是100%相信这是个好建议。
我可能会做下面这样的事情,并将 using 语句中的代码提取到一个单独的类/类中。
public IList<string> Post(DtoServiceA request)
{
//suppose if I control db connection like so
using (var conn = IDbConnectionFactory.Open())
{
//move code to a searapte "none servicestack service", which
//can be just a normal c# class
//so that the "boundary" is being controlled at service stack level
//and the actual code that does the job is extracted elsewhere
Resolve<NoneServiceStackServiceA>().DoSomething();
Resolve<NoneServiceStackServiceB>().DoSomething();
}
}
public IList<string> Post(DtoServiceB request)
{
//suppose if I control db connection like so
using (var conn = IDbConnectionFactory.Open())
{
//move code to a searapte "none servicestack service", which
//can be just a normal c# class
//so that the "boundary" is being controlled at service stack level
//and the actual code that does the job is extracted elsewhere
Resolve<NoneServiceStackServiceB>().DoSomething();
}
}
欢迎任何建议/建议。谢谢。
从资源使用的角度来看,这不是一个坏主意,因为打开额外的数据库连接对于连接池(SqlServer 的默认值(非常轻量级。
如果调用服务类似于"聚合服务",它只是将多个服务的输出组合到单个服务响应中,则很好,罗斯文客户详细信息服务中的示例如下:
public class CustomerDetailsService : Service
{
public CustomerDetailsResponse Get(CustomerDetails request)
{
var customer = Db.SingleById<Customer>(request.Id);
using (var orders = base.ResolveService<OrdersService>())
{
var ordersResponse = orders.Get(new Orders { CustomerId = customer.Id });
return new CustomerDetailsResponse
{
Customer = customer,
CustomerOrders = ordersResponse.Results,
};
}
}
}
否则,从代码架构的角度来看,它并不理想,因为它模糊了依赖关系图,我更愿意在共享依赖或扩展方法中提取通用功能,例如:
ServiceA
- SharedDep
ServiceB
- SharedDep
避免服务响应中的接口
附带说明一下,我强烈建议不要在服务响应中使用接口。集合很少被嘲笑,IList<T>
特别无用,因为它实际上总是隐藏一个具体的List<T>
,它需要转换为该才能访问其有用的LINQ扩展方法。