2

我创建了一个插件,它检查查询字符串中的参数并根据此 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));
        }
    }
}

我需要在我的服务中提供此用户对象,但我不想每次都检查 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; }
}
4

3 回答 3

1

您是否考虑过尝试使用IHttpRequest Items Dictionary来存储对象。您可以从任何过滤器或服务或任何可以访问 IHttpRequest 的地方访问这些项目。请参阅IHttpRequest的源代码。

请注意属性、服务和插件的执行顺序以及将项目存储在 Items 字典中的时间。

于 2013-03-19T17:37:06.613 回答
0

我需要在我的服务中使用此用户对象,但我不想每次都检查 DTO 并从那里提取

如果您没有在查询字符串中传递“用户 ID”,您的应用程序将如何了解用户?您可以将用户数据存储在Session中吗?使用 Session 假设客户端连接到您的应用程序并在客户端中保留一个 Session Id(ServiceStack 中的 ss-id 或 ss-pid cookie),可以在服务器上查找以获取“会话数据”。如果您可以使用 Session ,您可以从您的服务中检索数据,执行类似的操作

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

注意:您需要将用户数据保存到会话

有没有办法让来自插件的数据在全球范围内可供我的服务使用?但我看不到如何为需要在每个请求开始时实例化的 User 对象实现这一点。

这听起来像您想要一个全局请求过滤器。您已经在这样做了,但是您将其包装到插件中。

于 2013-03-19T18:13:57.897 回答
0

添加:

我们不想在 Service 中使用 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) { }

有什么建议么?

于 2013-03-20T05:53:39.930 回答