Search code examples
c#dependency-injectionautofacspecflow

Specflow.Autofac: Swap out a dependency after the container has been built


FYI: I am using SpecFlow.Autofac nuget package.

Following GetContainer method exists within a parent class library project.

    [ScenarioDependencies]
    public static ContainerBuilder GetContainerWithDependencies()
    {
        var containerBuilder = new ContainerBuilder();

        containerBuilder.RegisterType<PosMgmtScenarioCtx>().As<IScenarioContext>().InstancePerLifetimeScope();

        return containerBuilder;
    }

At a later point, within a child project (which references the parent), I attempt replacing the interface implementation with a new class but it does not work.

    [Given(@"...Step...")]
    public void GivenGenerateEmpWithXRefCode(some params)
    {
        using 
        (
            var scope = _lifetimeScope.BeginLifetimeScope(
                builder =>  {
                    // THIS DOES NOT WORK.
                    builder.RegisterType<EmployeeScenarioCtx>().As<IScenarioContext>();
                }
            )
        )
        {                
            _createUpdatePositionStepsLogic.PostPatchTheObject(service, "POST", "Employee", url, expectedStatusCode,
                version);
        }
    }

Need to replace IScenarioContext with EmployeeScenarioCtx instead of PosMgmtScenarioCtx.

Any help would be appreciated, thanks!


Solution

  • So, my question should have been how to override dependencies within a constructor using Autofac to which there are many answers on SO already. I don't have reputation to mark my question as a duplicate but please do so if necessary.

    Following answers helped me:

    1. https://stackoverflow.com/a/30836235/1524213
    2. https://stackoverflow.com/a/17054237/1524213

    This is how the eventual code looks now:

    using(var scope = _lifetimeScope.BeginLifetimeScope(
                    builder =>
                    {
                        builder.RegisterType<WithPayload>().WithParameter(
                            (p, c) => p.ParameterType == typeof(IScenarioContext),
                            (p, c) => c.Resolve<EmployeeScenarioCtx>()).As<IWithPayload>();
                    }
                )
            )
            {
                switch (version)
                {
                    case PosMgmtStepsVersion.V1:
                        var withPayload = scope.Resolve<IWithPayload>();
                        withPayload.GivenPOST_PATCH_EndPoint_WithStatusCodeCheck("POST", "Employee", UniqueIdentifier,
                            url,
                            expectedStatusCode);
                        break;
                    default:
                        throw new ArgumentOutOfRangeException(nameof(version), version, null);
                }