2013-03-11 6 views
5

私はローカライズされたデータを扱う必要があります。ローカライズされたすべての応答Dtosは同じプロパティを共有します。私。私はそれらのDtosをマークするためのインタフェース(ILocalizedDto)を定義しました。要求側では、ローカライズを要求する要求に対してILocalizedRequestがあります。要求と応答の両方を必要とするServiceStackプラグインを書く方法Dtos

使用IPlugin私はすでに必要な機能を実装することができました。しかし、実装がスレッドセーフではなく、さらにIHttpRequest.GetHashCode()を1つの要求/応答サイクルの識別子として使用できるかどうかはわかりません。

リクエストとレスポンスの両方を使用するServiceStackプラグインを実装する正しい方法は何でしょうか?私。そこにデータを格納するためのIHttpRequest.Contextがあるのですか、または応答時間に要求を取得することは可能ですか?

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であると仮定すると、通常、stuffはHttpContext.Itemsコレクションに格納できます。残念ながら、IHttpContextはそれを公開していないようです... http://msdn.microsoft.com/en-us/library/ms689291%28v=vs.90%29.aspx –

答えて

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

ここで興味深いのは、あなたのHTTPヘッダ、クッキー、またはフォーム・データのいずれかで言語を注入する機会を与える、var language = request.GetParam(LanguageKey) ?? request.GetItem(LanguageKey);です(該当する場合)をキー "X-Language"で置き換えます。それがこのように供給されていない場合は

を(あなたがまた...翻訳するためのデフォルトの言語を注入する別の?? DefaultLanguageを行うことができます)、要求のセットLanguageは、要求のItemsから読み込まれ、使用されています。

編集: また、pointed out by @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); 
    } 
} 
+0

また、Request DTOは 'IRequest .Dto'と 'IResponse.Dto'のレスポンスオブジェクト – mythz

+1

@mythz良いキャッチ! –

関連する問題