【问题标题】:ServiceStack Funq ReuseScope.Request injects same object instead of a new instanceServiceStack Funq ReuseScope.Request 注入相同的对象而不是新实例
【发布时间】:2015-08-18 02:32:03
【问题描述】:

ReuseScope.Request 有问题。即使我指定了ReuseScope.Request,我也会在每个请求上注入same 实例。我使用这两个调用来配置容器以获得 MasterConfig:

this.container.RegisterAutoWiredAs<ApiConfigFactory, IConfigFactory>().ReusedWithin(ReuseScope.Container);
this.container.Register(c => c.Resolve<IConfigFactory>().GetMasterConfig(true)).ReusedWithin(ReuseScope.Request);

GetMasterConfig(true) 方法返回一个新的具体 MasterConfig。但是,当我尝试在服务中使用 MasterConfig 时,每个请求都会得到相同的实例。

public class MyService
{
    private readonly MasterConfig masterConfig;

    public SaleService(MasterConfig masterConfig)
    {
        this.masterConfig = masterConfig;
    }

    public object Post(MyRequest request)
    {
        // **masterConfig is the same instance here on every request**
    }
}

如果我将 MasterConfig 寄存器上的范围更改为 ReuseScope.None,我会按预期加载一个新的 MasterConfig。我错过了什么?我注册 MasterConfig 的方式有问题吗?为什么ReuseScope.None 解决了这个问题?为什么ReuseScope.Request 给我同样的例子?

注意:

【问题讨论】:

    标签: servicestack funq


    【解决方案1】:

    我无法在自主机或 ASP.NET 主机中重现此问题。

    这适用于最新版本的 ServiceStack:

    //AppHost
    public class RequestScopeAppHost : AppSelfHostBase
    {
        public RequestScopeAppHost() 
          : base(typeof(RequestScopeAppHost).Name, typeof(RequestScopeService).Assembly) {}
    
        private static int counter = 0;
    
        public override void Configure(Container container)
        {
            container.Register(c => new MasterConfig {
                Id = Interlocked.Increment(ref counter)
            }).ReusedWithin(ReuseScope.Request);
        }
    }
    

    服务:

    public class MasterConfig
    {
        public int Id { get; set; }
    }
    
    public class GetMasterConfig : IReturn<MasterConfig> { }
    
    public class RequestScopeService : Service
    {
        private readonly MasterConfig config;
    
        public RequestScopeService(MasterConfig config)
        {
            this.config = config;
        }
    
        public object Any(GetMasterConfig request)
        {
            return config;
        }
    }
    

    测试:

    [TestFixture]
    public class RequestScopeIssue
    {
        private readonly ServiceStackHost appHost;
    
        public RequestScopeIssue()
        {
            appHost = new RequestScopeAppHost()
                .Init()
                .Start(Config.AbsoluteBaseUri);
        }
    
        [TestFixtureTearDown]
        public void TestFixtureTearDown()
        {
            appHost.Dispose();
        }
    
        [Test]
        public void Can_get_RequestScope_dependency()
        {
            var client = new JsonServiceClient(Config.AbsoluteBaseUri);
    
            Assert.That(client.Get(new GetMasterConfig()).Id, Is.EqualTo(1));
            Assert.That(client.Get(new GetMasterConfig()).Id, Is.EqualTo(2));
            Assert.That(client.Get(new GetMasterConfig()).Id, Is.EqualTo(3));
        }
    }
    

    在您的描述中,ReuseScope.None 也可以按预期工作,它不会重复使用实例。

    【讨论】:

      【解决方案2】:

      我也遇到了完全相同的问题,使用的是 ServiceStack 版本 4.5.6

      这是我的注册码

      container.RegisterAutoWiredAs<EventConditionalLoadingRepository, IEventConditionalLoadingRepository>()
          .ReusedWithin(ReuseScope.Request);
      
      container.RegisterAutoWiredAs<MetaRiskRepository, IMetaRiskRepository>()
          .ReusedWithin(ReuseScope.Request);
      
      container.RegisterAutoWiredAs<RiskStoreConnectivityService, IRiskStoreConnectivityService>()
          .ReusedWithin(ReuseScope.Request);
      
      container.Register<IUnitOfWork>(c =>
      {
          return new UnitOfWork();
      }).ReusedWithin(ReuseScope.Request);
      
      container.Register(c => (IUnitOfWorkEnlistable)c.Resolve<IUnitOfWork>())
          .ReusedWithin(ReuseScope.Request); 
      

      这是我使用这些依赖项的服务

      public AnalysisServiceStackService(
          IEventConditionalLoadingRepository eventConditionalLoadingRepository,
          IMetaRiskRepository metaRiskRepository,
          IUnitOfWork unitOfWork)
      {
      
          _eventConditionalLoadingRepository = eventConditionalLoadingRepository;
          _metaRiskRepository = metaRiskRepository;
          _unitOfWork = unitOfWork;
          _log.Information("AnalysisServiceStackService constructed");
      }
      

      您可以看到我在那里有一个日志语句,当我通过邮递员访问此服务以进行顺序请求时,我会记录此类事情

      2017-03-30 15:34:10 [Information] AnalysisServiceStackService constructed
      2017-03-30 15:34:11 [Information] AnalysisServiceStackService constructed
      2017-03-30 15:34:12 [Information] AnalysisServiceStackService constructed
      2017-03-30 15:34:13 [Information] AnalysisServiceStackService constructed
      2017-03-30 15:34:14 [Information] AnalysisServiceStackService constructed
      2017-03-30 15:34:15 [Information] AnalysisServiceStackService constructed
      2017-03-30 15:34:16 [Information] AnalysisServiceStackService constructed
      2017-03-30 15:34:17 [Information] AnalysisServiceStackService constructed
      

      所以我知道服务本身应该尝试解析它所需的 IOC 组件的新 PerRequest 实例。

      如果我随后使用 Visual Studio 并使用调试“生成对象 ID”功能来检查 IOC 容器为我提供的内容,它们是同一个实例。

      调用 1:第一个请求

      查看由 Visual Studio 创建的 #1 对象 ID

      调用 2:第二次请求

      查看#1 对象 ID,这意味着它不应该是同一个实例。它应该是新请求的新实例

      为了证明这些是不同的调用,这里是构造函数运行两次的日志,每个请求一次

      唯一为我解决此问题的是 Reuse.None

      的建议修复

      但如果我必须这样做,我不妨只使用 AutoFac 适配器(我更愿意使用它)并使用标准 AutoFac INstancePerLifeTimeScope:http://docs.autofac.org/en/latest/lifetime/instance-scope.html#instance-per-lifetime-scope

      有什么想法吗?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多