1
votes

The following class takes a primitive on the constructor, so I need to tell AutoFac how to generate said value using a delegate:

public class BackgroundTaskScheduler : IStartable
{
    private readonly IJobRunner _jobRunner;
    private int _triggerMilliseconds;


    public BackgroundTaskScheduler(IJobRunner jobRunner, int triggerMilliseconds)
    {
        _jobRunner = jobRunner;
        _triggerTimespan = triggerMilliseconds;
    }
}


public static class AutoFac
{
    public static void Configure()
    {
        var builder = new ContainerBuilder();

        var triggerInterval =
                int.Parse(
                    ConfigurationManager.AppSettings["TaskScheduleTriggerMilliseconds"]);

        builder.Register(
            c => new BackgroundTaskScheduler(c.Resolve<IJobRunner>(), triggerInterval)).AsImplementedInterfaces().SingleInstance();

        builder.RegisterAssemblyTypes(typeof (RegistrationController).Assembly)
            .AsImplementedInterfaces()
            .AsSelf();

        IContainer container = builder.Build();

    }
}

However, Autofac appears to ignore my registration as evidenced by the exception it throws when resolving an instance of BackgroundTaskScheduler:

None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Delen.Server.Tasks.BackgroundTaskScheduler' can be invoked with the available services and parameters: Cannot resolve parameter 'System.Int32 triggerMilliseconds' of constructor 'Void .ctor(Delen.Server.Tasks.IJobRunner, System.Int32)'.

I've successfully used the IContainerBuilder.Register method before in exactly such a scenario but I've no clue why it's not working this go around.

Update 1

Changing the order of the registrations did not make a difference.

Update 2

Here's an alternative way to achieve the same result as the accepted Answer:

builder.RegisterAssemblyTypes(typeof(IJobRunner).Assembly)
    .Except<BackgroundTaskScheduler>()
    .AsImplementedInterfaces()
    .AsSelf()
1

1 Answers

1
votes

The order of the registrations does mater beside that using the assembly scanning features can be dangerous if you also want to register types by hand because you could end up interfering registrations.

In your case you are registering your BackgroundTaskScheduler twice

  • once with the correct parameters when calling builder.Register
  • the second type when calling builder.RegisterAssemblyTypes this time without the required triggerInterval parameter.

So you've ended up two registrations where one of them is not correct so when calling builder.Build you get the exception.

To fix it you need to exclude all the hand registered types in the RegisterAssemblyTypes call:

builder.RegisterAssemblyTypes(typeof(AutofacRegistrationOrderTest).Assembly)
    .Where(t => t != typeof(BackgroundTaskScheduler))
    .AsImplementedInterfaces()
    .AsSelf();

builder.Register(
    c => new BackgroundTaskScheduler(c.Resolve<IJobRunner>(), triggerInterval))
    .AsImplementedInterfaces()
    .SingleInstance();