2013-03-11 25 views
5

我需要为本地化数据提供服务。本地化的所有响应Dtos都共享相同的属性。即我定义了一个接口(ILocalizedDto)来标记这些Dtos。在请求方面,需要本地化的请求有ILocalizedRequest如何编写需要请求和响应的ServiceStack插件Dtos

使用IPlugin我已经设法实现了所需的功能。但是我确定实现不是线程安全的,另外我不知道我是否可以使用IHttpRequest.GetHashCode()作为一个请求/响应循环的标识符。

实现一个ServiceStack插件的正确方法是什么?它使用请求和响应Dto?即是否有一些IHttpRequest.Context存储数据或可以在响应时间获取请求dto?

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(); 
    } 
} 
+0

看来你对IHttpRequest /响应的问题将被执行特定的。假设实现是ASP.NET,通常可以将东西存储在HttpContext.Items集合中。不幸的是,IHttpContext似乎没有公开它...... http://msdn.microsoft.com/en-us/library/ms689291%28v=vs.90%29.aspx – 2013-05-21 22:24:57

回答

2

第一关:为什么你需要请求本身,当所有你需要的是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);,这让你有机会与任何HTTP标头,Cookie或表单数据注入语言(如果适用)和“X语言”键。 (您也可以做另一个?? DefaultLanguage以注入默认语言以进行翻译...)

如果未以此方式提供,请求的集合Language将从请求的Items中读取并使用。

编辑: 此外,作为pointed out by @mythz,你也可以用request.Dto访问请求DTO在InterceptResponse方法:

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); 
    } 
} 
+0

此外请求DTO保存在'IRequest .Dto'和响应对象在'IResponse.Dto' – mythz 2015-08-23 22:27:57

+1

@mythz好赶上! – 2015-08-23 22:40:07