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 дает мне тот же экземпляр?

Примечание:


person Bryan Cox    schedule 18.08.2015    source источник


Ответы (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 также работает по назначению, оно не использует экземпляры повторно.

person mythz    schedule 18.08.2015

У меня также была точно такая же проблема с использованием 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 и использую функцию отладки «Создать идентификатор объекта», чтобы проверить, что дает мне контейнер IOC, они являются одним и тем же экземпляром.

Звонок 1: первый запрос

см. идентификатор объекта № 1, созданный Visual Studio

Идентификатор №1

Звонок 2: второй запрос

См. идентификатор объекта № 1, который означает, что это тот же экземпляр, которым НЕ должно быть. Это должен быть новый экземпляр для нового запроса

Тот же объект

И просто чтобы доказать, что это разные вызовы, вот логи для Конструктора, запускаемого дважды, по одному разу для каждого запроса

Регистрация после 2 запросов

Единственное, что исправило это для меня, - это предложенное исправление Reuse.None.

Но если мне нужно это сделать, я могу просто использовать адаптер AutoFac (который я бы предпочел использовать в любом случае) и использовать стандартный AutoFac INstancePerLifeTimeScope: http://docs.autofac.org/en/latest/lifetime/instance-scope.html#instance-per-lifetime-scope

Есть идеи?

person sacha barber    schedule 30.03.2017