如何编写一个需要请求和响应Dtos的ServiceStack插件
本文关键字:响应 求和 请求 Dtos 插件 ServiceStack 何编写 一个 | 更新日期: 2023-09-27 18:03:29
我需要服务本地化的数据。所有本地化的响应dto都共享相同的属性。也就是说,我定义了一个接口(ILocalizedDto
)来标记那些dto。在请求端,有一个ILocalizedRequest
用于需要本地化的请求。
使用IPlugin
,我已经设法实现了所需的功能。然而,我很确定,实现不是线程安全的,另外我不知道我是否可以使用IHttpRequest.GetHashCode()作为一个请求/响应周期的标识符。
实现ServiceStack插件的正确方法是使用请求和响应Dto?也就是说,是否有一些IHttpRequest。上下文存储数据,还是可以在响应时获取请求?
internal class LocalizationFeature : IPlugin
{
public static bool Enabled { private set; get; }
/// <summary>
/// Activate the localization mechanism, so every response Dto which is a <see cref="ILocalizedDto" />
/// will be translated.
/// </summary>
/// <param name="appHost">The app host</param>
public void Register(IAppHost appHost)
{
if (Enabled)
{
return;
}
Enabled = true;
var filter = new LocalizationFilter();
appHost.RequestFilters.Add(filter.RequestFilter);
appHost.ResponseFilters.Add(filter.ResponseFilter);
}
}
// My request/response filter
public class LocalizationFilter
{
private readonly Dictionary<int,ILocalizedRequest> localizedRequests = new Dictionary<int, ILocalizedRequest>();
public ILocalizer Localizer { get; set; }
public void RequestFilter(IHttpRequest req, IHttpResponse res, object requestDto)
{
var localizedRequest = requestDto as ILocalizedRequest;
if (localizedRequest != null)
{
localizedRequests.Add(GetRequestId(req), localizedRequest);
}
}
public void ResponseFilter(IHttpRequest req, IHttpResponse res, object response)
{
var requestId = GetRequestId(req);
if (!(response is ILocalizedDto) || !localizedRequests.ContainsKey(requestId))
{
return;
}
var localizedDto = response as ILocalizedDto;
var localizedRequest = localizedRequests[requestId];
localizedRequests.Remove(requestId);
Localizer.Translate(localizedDto, localizedRequest.Language);
}
private static int GetRequestId(IHttpRequest req)
{
return req.GetHashCode();
}
}
首先:当您需要的只是Language
属性的值时,为什么需要请求本身?
下面的代码是您的场景的合法解决方案:
public class LocalizationFeature : IPlugin
{
public const string LanguageKey = "X-Language";
public void Register(IAppHost appHost)
{
this.GlobalRequestFilters.Add(this.InterceptRequest);
this.GlobalResponseFilters.Add(this.InterceptResponse);
}
private void InterceptRequest(IRequest request,
IResponse response,
object dto)
{
var localizedRequest = dto as ILocalizedRequest;
if (localizedRequest != null)
{
request.SetItem(LanguageKey,
localizedRequest.Language);
}
}
private void InterceptResponse(IRequest request,
IResponse response,
object dto)
{
var localizedDto = dto as ILocalizedDto;
if (localizedDto != null)
{
var language = request.GetParam(LanguageKey) ?? request.GetItem(LanguageKey);
if (!string.IsNullOrEmpty(language))
{
Localizer.Translate(localizedDto,
language);
}
}
}
}
这里有趣的是var language = request.GetParam(LanguageKey) ?? request.GetItem(LanguageKey);
,它让您有机会使用关键字"X-Language"注入HTTP头、cookie或表单数据(如果适用)的语言。(你也可以做另一个?? DefaultLanguage
注入一个默认语言来翻译…)
如果不以这种方式提供,则从请求的Items
中读取请求的Language
并使用。
编辑:此外,正如@mythz所指出的,您还可以在InterceptResponse
方法中使用request.Dto
访问请求DTO:
private void InterceptResponse(IRequest request,
IResponse response,
object dto)
{
var localizedRequest = request.Dto as ILocalizedRequest;
var localizedDto = dto as ILocalizedDto;
if (localizedRequest != null
&& localizedDto != null)
{
Localizer.Translate(localizedDto,
localizedRequest.Language);
}
}