我在4.0.31中有一个工作服务,如下所示:
public object Post(MyDTO request)
{
foreach (var uploadedFile in base.Request.Files)
{
... do something ...
}
return new MyDTOResponse();
}
一切都很好,我很高兴!
但是现在,我想从另一个服务中调用相同的服务方法,显然这样做的方法是:
public object Post(MyOtherDTO request)
{
var myService = base.ResolveService<MyService>();
// now I call some new method I wrote to bypass the file upload part, since
// myService.Post() doesn't know about the file upload part
var myResponse = myService.NewMethodThatLetsMePassAStreamToTheOtherService(streamData);
... do other stuff...
return new MyOtherDTOResponse();
}
虽然我不是不开心,但它确实在两个服务之间创建了一个硬依赖关系,所以我不像我通常使用ServiceStack一样激动!
有没有更优雅的方式将它们组合在一起?我可能只是错过了一些非常非常明显的东西......
答案 0 :(得分:3)
我不是100%清楚问题是什么,如果它是如何在服务之间共享逻辑的?然后,您可以从每个服务类中提取通用逻辑,并引用两个服务中的共享代码。
如果不需要依赖项,我将重构可重用扩展方法背后的共享代码。
如果需要依赖关系,我将在一个共享逻辑类后面重构它,这是两个服务中的依赖关系,请参阅sharing logic between MVC and ServiceStack answer中的IGreeter
示例:
public class MyService1 : Service
{
public ISharedDep SharedDep { get; set]
public object Any(Request1 request)
{
//...
}
}
public class MyService2 : Service
{
public ISharedDep SharedDep { get; set]
public object Any(Request2 request)
{
//...
}
}
如果许多服务使用的公共代码需要base.Request
上下文而不是将其移动到公共服务基类:
public class MyServiceBase : Service
{
public ISharedDep SharedDep { get; set]
public object SharedMethod(object request)
{
//...
}
}
public class MyServices1 : MyServiceBase { ... }
public class MyServices2 : MyServiceBase { ... }
如果您不想使用基类,也可以在扩展方法后面重新计算:
public static void MyServiceExtensions
{
public static object SharedMethod(this IServicBase service, object request)
{
var sharedDep = service.TryResolve<ISharedDep>();
return sharedDep.SharedMethodWithRequestCtx(request, service.Request);
}
}
如果问题是关于松散耦合的方式调用服务而不引用实现本身,您可以使用ServiceController执行Request DTO:
public class MyService : Service
{
public object Any(Request requestDto)
{
var altDto = new AltRequest { Id = requestDto.Id };
var response = HostContext.ServiceController.Execute(altDto, base.Request);
//...
}
}
注意:此API在v4.0.32 +。
中以base.ExecuteRequest(requestDto)
的形式提供
如果问题是如何执行处理文件上传的服务,则有一个example in the embedded version of HttpBenchmarks显示如何使用自定义请求上下文来调用处理HTTP文件上载的服务,该自定义请求上下文使用本地文件系统文件:
using (var admin = Resolve<AdminServices>())
{
//...
var dir = new FileSystemVirtualPathProvider(this, Config.WebHostPhysicalPath);
var files = dir.GetAllMatchingFiles("*.txt")
.Concat(dir.GetAllMatchingFiles("*.zip"));
admin.Request = new BasicRequest
{
Files = files.Map(x => new HttpFile {
ContentLength = x.Length,
ContentType = MimeTypes.GetMimeType(x.Name),
FileName = x.Name,
InputStream = x.OpenRead(),
} as IHttpFile).ToArray()
};
if (admin.Request.Files.Length > 0)
{
admin.Post(new UploadTestResults
{
TestPlanId = 1,
TestRunId = testRun.Id,
CreateNewTestRuns = true,
});
}
}