0

I could well be misunderstanding something here, so perhaps there is a simple answer here but I'm currently scratching my head.

I have a class UnitOfWork that implements IUnitOfWork (yes yes I know). The constructor for unit of work takes an IPrincipalFactory. TResponder is the top level of the graph which takes an IUnitOfWork.

I'm trying to register the ApplicationPrincipalFactory as a specific instance in a lifetime scope... it's dependant on some properties passed to the HandleAsync function. I'm doing the following:

    public async Task<TResponse> HandleAsync<TMessage, TResponse, TResponder>(TMessage message)
        where TMessage : class
        where TResponder : IRespondAsync<TMessage, TResponse>
    {
        using (var scope = this.BeginLifetimeScope(message))
        {
            var responder = scope.Resolve<TResponder>();
            return await responder.Respond(message);
        }
    }

    private ILifetimeScope BeginLifetimeScope<TMessage>(TMessage message)
    {
        var unwrapped = GetDomainContext(message);
        var applicationPrincipalFactory = this.CreateApplicationPrincipalFactory(unwrapped);

        var lifetime = this.container.BeginLifetimeScope(
            r => r.RegisterInstance(applicationPrincipalFactory).As<IPrincipalFactory>());

        return lifetime;
    }

    private ApplicationPrincipalFactory CreateApplicationPrincipalFactory(IDomainContext unwrapped)
    {
        var applicationPrincipalFactory =
            new ApplicationPrincipalFactory(
                unwrapped.Tenant,
                unwrapped.ActingTenant,
                unwrapped.Username);

        return applicationPrincipalFactory;
    }

Based on everything I've read, defining the dependency within BeginLifetimeScope(r => should override the parent container binding, so when I call resolve, it should all slot neatly together.

However, I get an exception:

None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Platform.Engine.Persistence.UnitOfWork' can be invoked with the available services and parameters: Cannot resolve parameter 'Platform.Engine.Security.IPrincipalFactory principalFactory' of constructor

I am not registering the IPrincipalFactory anywhere other than in this method. The IUnitOfWork is defined in the outer scope as follows:

builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();

I have also tried re-defining the unitofwork registration within the child container in case it was an issue cause by registering it in the outer container rather than the lifetime one:

        var lifetime = this.container.BeginLifetimeScope(
            r => r.RegisterInstance(applicationPrincipalFactory).As<IPrincipalFactory>());

        var overrides = new ContainerBuilder();
        overrides.RegisterType<UnitOfWork>().As<IUnitOfWork>();
        overrides.Update(lifetime.ComponentRegistry);

        return lifetime;

I'm not sure what I'm missing... any ideas or suggestions?

beyond-code
  • 1,423
  • 1
  • 12
  • 20

1 Answers1

0

Register your factory with the rest of your types during the initial container configuration.

builder.RegisterType<ApplicationPrincipalFactory>().As<IPrincipalFactory>();

Then in your lifetime scope resolve a delegate factory that you can pass the context into.

var factory = container.Resolve<Func<IDomainContext, IPrincipalFactory>>();
var instance = factory(context);

You could also add three string parameters to the Func<> signature, but since you already have a nice context object I would just pass that in instead.

Finally, use the factory as needed.

instance.DoesSomethingButNotSureWhat();

That will prevent you from having to update the lifetime scope just to pass in the context parameter.

Alex Meyer-Gleaves
  • 3,821
  • 21
  • 11