ServiceStack Funq ReuseScope.Request внедряет тот же объект вместо нового экземпляра
У меня проблема с ReuseScope.Request
, Я получаю один и тот же экземпляр при каждом запросе, хотя я указываю ReuseScope.Request
, Я настроил контейнер, используя эти два вызова, чтобы получить 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
дай мне такой же экземпляр?
Замечания:
2 ответа
Я не смог воспроизвести это ни на самом хосте, ни на хосте 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
также работает как задумано, он не использует экземпляры повторно.
У меня тоже была точно такая же проблема, с использованием 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
Поэтому я знаю, что сама служба должна пытаться разрешить новый экземпляр PerRequest тех компонентов IOC, в которых она нуждается.
Если я затем использую Visual studio и использую функцию отладки "Make Object ID", чтобы проверить, что дает мне контейнер IOC, это один и тот же экземпляр.
Звоните 1: 1-й запрос
см. идентификатор объекта № 1, созданный Visual Studio
Звонок 2: 2-й запрос
Посмотрите #1 идентификатор объекта, который означает, что это тот же экземпляр, который НЕ должен быть. Это должен быть новый экземпляр для нового запроса
И просто чтобы доказать, что это разные вызовы, вот журналы для Конструктора, запускаемого дважды, один раз для каждого запроса.
Единственное, что исправило это для меня, было предложено исправить Reuse.None
Но если мне нужно сделать это, я мог бы просто использовать адаптер AutoFac (который я бы предпочел использовать в любом случае) и использовать стандартный AutoFac INstancePerLifeTimeScope: http://docs.autofac.org/en/latest/lifetime/instance-scope.html
Есть идеи?