2013-03-19 79 views
2

我已經創建了一個插件,用於檢查查詢字符串中的參數,並根據此ID加載用戶對象,並使用它填充任何請求DTO的 。 (從BaseRequest我的所有要求DTO的繼承具有CurrentUser屬性)是否有可能在運行時注入一個對象實例到服務

public class CurrentUserPlugin : IPlugin 
{ 
    public IAppHost CurrentAppHost { get; set; } 

    public void Register(IAppHost appHost) 
    { 
     CurrentAppHost = appHost; 
     appHost.RequestFilters.Add(ProcessRequest); 
    } 

    public void ProcessRequest(IHttpRequest request, IHttpResponse response, object obj) 
    { 
     var requestDto = obj as BaseRequest; 

     if (requestDto == null) return; 

     if (request.QueryString["userid"] == null) 
     { 
      throw new ArgumentNullException("No userid provided"); 
     } 

     var dataContext = CurrentAppHost.TryResolve<IDataContext>(); 
     requestDto.CurrentUser = dataContext.FindOne<User>(ObjectId.Parse(requestDto.uid)); 

     if (requestDto.CurrentUser == null) 
     { 
      throw new ArgumentNullException(string.Format("User [userid:{0}] not found", requestDto.uid)); 
     } 
    } 
} 

我需要在我的服務提供這樣的用戶對象,但我不希望每次都檢查DTO,並從那裏提取。有沒有一種方法可以使全局插件中的數據可用於我的服務?我也想知道是否有另一種實例化這個對象的方式,因爲我的單元測試中,插件沒有運行,因爲我直接調用了我的服務。

所以,我的問題是,而不是使用插件,我可以在運行時注入一個用戶實例到我的服務?我已經使用IoC來注入不同的數據庫處理程序,具體取決於是否在測試模式下運行,但我無法看到如何爲每個請求開始時需要實例化的User對象實現此目的。

下面是我如何在appHost中注入DataContext的示例。

container.Register(x => new MongoContext(x.Resolve<MongoDatabase>())); 
container.RegisterAutoWiredAs<MongoContext, IDataContext>(); 

這是我的BaseService的一個例子。理想情況下,我想在我的服務上擁有CurrentUser屬性。

public class BaseService : Service 
{ 
    public BaseService(IDataContext dataContext, User user) 
    { 
     DataContext = dataContext; 
     CurrentUser = user; // How can this be injected at runtime? 
    } 

    public IDataContext DataContext { get; private set; } 
    public User CurrentUser { get; set; } 
} 

回答

0

添加:

我們不希望因爲我們希望在我們的測試中直接使用服務使用HttpContext的服務內。

優勢,爲生活離不開它

如果你不需要有什麼能夠阻止你從消息隊列中有你的相同 IService實現處理請求訪問HTTP 請求上下文這 我們已經完成了內部項目(順便說一句,這是在asynconeway端點後面的動機 ,用於表示延遲執行的安全延遲執行請求)。

http://www.servicestack.net/docs/framework/accessing-ihttprequest

而且我們不使用HTTP調用運行測試。

所以我們的解決方案是:

public class UserService 
    { 
     private readonly IDataContext _dataContext; 

     public UserService(IDataContext dataContext) 
     { 
      _dataContext = dataContext; 
     } 

     public User GetUser() 
     { 
      var uid = HttpContext.Current.Request.QueryString["userId"]; 

      return _dataContext.Get<User>(uid); 
     } 
    } 

container.Register(x => new UserService(x.Resolve<IDataContext>()).GetUser()).ReusedWithin(ReuseScope.Request); 

這是服務簽名:

public SomeService(IDataContext dataContext, User user) { } 

有什麼建議?

+0

這是我的同事提出的解決方案,我們不想在我們的服務中使用http請求上下文特定的功能,因爲我們直接調用我們的測試,而無需通過http堆棧。感謝所有回覆 – Martin 2013-03-21 16:37:46

1

你有沒有想過嘗試使用IHttpRequest項目字典來存儲對象。您可以從任何過濾器或服務或任何可以訪問IHttpRequest的地方訪問這些項目。請參閱src的IHttpRequest

請注意您的屬性,服務和插件的執行順序以及將項目存儲在項目字典中的順序。

0

我需要在我的服務提供這樣的用戶對象,但我不希望每次都檢查DTO,並從那裏

提取您的應用程序將如何瞭解用戶,如果你不在查詢字符串中傳遞'userid'?您能否將用戶數據存儲在Session?使用會話假定客戶端已連接到您的應用程序,並在客戶端持久存儲可在服務器上查找以獲取「會話數據」的會話Id(ssd-id或ss-pid cookie,位於ServiceStack中)。如果你可以使用會話你可以從你的服務的數據做這樣的事情

base.Session["UserData"] or base.SessionAs<User>(); 

注意:您將需要save your User data to the Session

有沒有一種方法,使從全球範圍提供給我服務的插件數據?但我不明白如何爲每個請求開始時需要實例化的User對象實現此目的。

這聽起來像是你想要一個global request filter。你已經這樣做了,但是你將它包裝到一個插件中。

相關問題