我创建了一个插件,用于检查查询字符串中的参数,并根据此ID加载用户对象并填充 任何请求DTO与它。 (我的所有请求DTO都继承自具有CurrentUser属性的BaseRequest)
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));
}
}
}
我需要在我的服务中使用此User对象,但我不想每次检查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 :(得分:1)
您是否考虑过尝试使用 IHttpRequest Items Dictionary 来存储对象。您可以从任何过滤器或服务或任何可以访问IHttpRequest的地方访问这些项目。请参阅src了解IHttpRequest。
请注意您的属性,服务和插件执行的顺序以及将项目存储在Items字典中的顺序。
答案 1 :(得分:0)
我需要在我的服务中提供此User对象,但我不想每次检查DTO并从中提取
如果你没有在查询字符串中传递'userid',你的应用程序将如何知道用户?你能将用户数据存储在Session吗?使用会话假定客户端已连接到您的应用程序并在客户端中保留会话ID(ServiceStack中的ss-id或ss-pid cookie),可以在服务器上查找以获取“会话数据”。如果您可以使用会话,您可以从服务中检索数据,如
base.Session["UserData"] or base.SessionAs<User>();
注意:您需要save your User data to the Session
有没有办法让我的服务全局可以使用插件中的数据?但我无法看到如何为每个请求开始时需要实例化的User对象实现此目的。
听起来你想要global request filter。你有点已经这样做但是你把它包装成插件。
答案 2 :(得分:0)
添加:
我们不想在服务中使用HttpContext,因为我们希望直接在测试中使用Service。
没有它的生活优势
如果您不需要访问HTTP 请求上下文没有什么能阻止你拥有相同的内容 IService实现处理来自消息队列的请求 我们已经完成了内部项目(顺便说一下,这是动机 在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) { }
有什么建议吗?