gpt4 book ai didi

c# - ServiceStack中如何使用IRequiresRequest注入(inject)IRequest?

转载 作者:行者123 更新时间:2023-11-30 15:21:31 33 4
gpt4 key购买 nike

我需要访问请求上下文,特别是我的自定义类中的项目,我不想让它从 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; }
}

https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Web/IRequiresRequest.cs

但是,当从真正的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哪里提到

Note: ServiceStack's Service base class already implements IRequiresRequestContext which allows you to access the IRequestContext with base.RequestContext and the HTTP Request and Response with base.Request and base.Response.

我相信 IRequiresRequestContext 现在称为 IRequiresRequest,所以我认为应该更新文档。

Updated: full code to demo my original intention:

    [Route("/test", Verbs = "GET")]
public class Dto : IReturnVoid
{ }

public class DtoService : Service
{
//So that IGetContextItems is taken care of by IDependencyThatUsesIGetContextItems
public IDependencyThatUsesIGetContextItems DependencyThatUsesIGetContextItems { get; set; }

public void Get(Dto req)
{
DependencyThatUsesIGetContextItems.SomeMethod();
}
}

public interface IGetContextItems
{
string Get(string key);
}
//since ContextItemsGetter implmeents IRequiresRequest
//I can still easily test any service that uses IGetContextItems by mocking IGetContextItems
public class ContextItemsGetter : IGetContextItems, IRequiresRequest
{
public IRequest Request { get; set; }

public string Get(string key)
{
//either through injection
//return Request.Items[key].ToString();

//or some static class
//return RequestContext.RequestItems.Items[key].ToString();
return RequestContext.Instance.Items[key].ToString();
}
}

public interface IDependencyThatUsesIGetContextItems
{
string SomeMethod();
}
public class DependencyThatUsesIGetContextItems : IDependencyThatUsesIGetContextItems
{
//this will be inejcted
public IGetContextItems ContextItemsGetter { get; set; }

public string SomeMethod()
{
var a = ContextItemsGetter.Get("SomeKey");
return "blah";
}
}

最佳答案

IRequiresRequest只注入(inject)当前的 IRequest到您的Service 类和Validation Filters,它不会将 IRequest 注入(inject)到您的依赖项中,这些依赖项直接从 IOC 解析并且无法访问当前 IRequest能够注入(inject)。

还有ServiceStack的方便ServiceAbstractValidator<T>基类已经实现 IRequiresRequest所以在大多数情况下,IRequiresRequest 所在的地方applys 已经实现,所以你不需要自己实现它。

传递 IRequest 的推荐方法进入您的依赖项是将它们作为参数从您的服务传递,例如:

public class MyServices : Service
{
public IGetContextItems ContextItems { get; set; }

public object Get(Request request)
{
return ContextItems.Get(base.Request, request.Id);
}
}

您确实有机会通过覆盖 OnPreExecuteServiceFilter() 来检查和修改您的服务实例,然后再执行您的服务。在你的 AppHost 中通过并注入(inject) IRequest在实现 IRequiresRequest 的每个服务依赖项中与:

public override object OnPreExecuteServiceFilter(IService service, 
object request, IRequest req, IResponse res)
{
service.InjectRequestIntoDependencies(req);
return request;
}

只要每个父级实现 IRequiresRequest,调用下面的扩展方法就会递归地填充您的服务依赖关系图。 :

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

但是你需要注意不要执行IRequiresRequest在您的任何 Singleton 依赖项(默认范围)上,因为它不是 ThreadSafe,而将 IRequest 作为参数传递。

另外,为了避免将您的逻辑类耦合到 ServiceStack,我会考虑仅从 IRequest 传递您的依赖项所需的内容。而不是 IRequest实例本身,这也将使它更容易测试。

关于c# - ServiceStack中如何使用IRequiresRequest注入(inject)IRequest?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37472059/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com