我需要访问请求上下文,特别是我的自定义类中的项目,我不想让它继承自ServiceStack
服务或在我的服务中设置它。
因此,如果我有一个类如下,实现者类(ContextItemsGetter
)也实现了IRequiresRequest
,我希望填充Request
属性。
public interface IGetContextItems
{
string Get(string key);
}
public class ContextItemsGetter : IGetContextItems, IRequiresRequest
{
public string Get(string key)
{
//someway to access http context items
//im RequestContext.Instance.Items[key] e.g. Prop1 Prop2
//or Request.blah but Request is always null
}
public IRequest Request { get; set; }
}
但是,当从真正的 HTTP请求或 redis消息请求调用SessionIdGetter时,请求始终为空。难道我做错了什么?目的是解耦并使用Items在http请求和redis消息请求之间传递信息。
我也尝试使用RequestContext.Instance.Items,这对HTTP请求有效,但在redis消息请求期间,项目不在那里,我在调用ExecuteMessage之前填充的键不存在。
var req = new BasicRequest { Verb = HttpMethods.Get };
req.Items.Add("Prop1", m.GetBody().Prop1);
req.Items.Add("Prop2", m.GetBody().Prop2);
var result = HostContext.ServiceController.ExecuteMessage(m, req);
我使用的是4.0.50版本。
此外,此页面Access HTTP specific features in services提及
注意:
ServiceStack
的服务基类已实现IRequiresRequestContext
,允许您使用IRequestContext
访问base.RequestContext
,使用{{1}访问HTTP请求和响应}和base.Request
。
我相信base.Response
现在称为IRequiresRequestContext
,所以我认为应该更新文档。
已更新: 完整代码以演示我的初衷:
IRequiresRequest
答案 0 :(得分:4)
IRequiresRequest
仅将当前IRequest
注入您的服务类和验证过滤器,它不会将IRequest注入您的依赖性直接从IOC解决,并且无法访问当前的IRequest以便能够注入。
此外,ServiceStack方便的Service
和AbstractValidator<T>
基类已实施IRequiresRequest
,因此在大多数情况下IRequiresRequest
适用的地方已经实施,因此您不应该#39;需要自己实现它。
将IRequest
传递给依赖项的推荐方法是将它们作为参数传递给您的服务,例如:
public class MyServices : Service
{
public IGetContextItems ContextItems { get; set; }
public object Get(Request request)
{
return ContextItems.Get(base.Request, request.Id);
}
}
您有机会在执行服务之前检查和修改服务实例,方法是覆盖AppHost中的OnPreExecuteServiceFilter()
,然后在实现{的每个服务依赖项中注入IRequest
{ {1}}使用:
IRequiresRequest
只要每个父项实现public override object OnPreExecuteServiceFilter(IService service,
object request, IRequest req, IResponse res)
{
service.InjectRequestIntoDependencies(req);
return request;
}
,以下调用以下扩展方法将以递归方式填充服务依赖关系图:
IRequiresRequest
但是你需要小心不要在你的任何Singleton依赖项(默认范围)上实现public static class ServiceExtensions
{
public static void InjectRequestIntoDependencies(this object instance, IRequest req)
{
foreach (var pi in instance.GetType().GetPublicProperties())
{
var mi = pi.GetGetMethod();
if (mi == null)
continue;
var dep = mi.Invoke(instance, new object[0]);
var requiresRequest = dep as IRequiresRequest;
if (requiresRequest != null)
{
requiresRequest.Request = req;
requiresRequest.InjectRequestIntoDependencies(req);
}
}
}
}
,因为它不是ThreadSafe而是将IRequest作为参数传递。
另外,为避免将逻辑类与ServiceStack耦合,请考虑仅从IRequiresRequest
而不是IRequest
实例本身传递依赖项所需的内容,这样也可以更容易地进行测试。