是否可以在运行时将对象实例注入服务

时间:2013-03-19 15:49:02

标签: servicestack

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

3 个答案:

答案 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) { }

有什么建议吗?