This project is read-only.

Change in behaviour of <container>.GetInstance(Type type) after upgrading from 2.4.1 to 2.7.0

Jan 26, 2015 at 3:31 PM
I recently upgraded the version of Simple Injector in a Windows Service project that uses Quartz.NET to schedule jobs from 2.4.1 to 2.7.0. After doing this, I noticed a breaking change in the behaviour of <container>.GetInstance(Type type).

I register my job types with the container using the following code:
var jobTypes = from type in typeof (OptionExpiryJob).Assembly.GetExportedTypes()
                           where typeof (IJob).IsAssignableFrom(type)
                           where !type.IsAbstract && !type.IsGenericTypeDefinition
                           select type;

            container.RegisterAll<IJob>(jobTypes);
I then have a Job Factory that creates instances of jobs in response to Quartz.NET firing a trigger. My factory implementation looks like this:
 public class SimpleInjectorJobFactory : IJobFactory
    {
        private readonly Container _container;

        public SimpleInjectorJobFactory(Container container)
        {
            _container = container;
        }

        public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            try
            {
                return new JobDecorator((IJob)_container.GetInstance(bundle.JobDetail.JobType));
            }
            catch (Exception ex)
            {
                throw new SchedulerException(
                    String.Format(CultureInfo.InvariantCulture, "Problem instantiating class '{0}'",
                                  bundle.JobDetail.JobType.FullName), ex);
            }
        }

        public void ReturnJob(IJob job)
        {
        // No implementation required for SimpleInjector Ioc container
        }
    }
When a trigger fires, Quartz.NET provides information about the concrete type that represents the job associated with the trigger. With Simple Injector 2.4.1, I could call <container>.GetInstance with this type object to get an instance of the job to be executed. However, after upgrading to 2.7.0, Simple Injector now says that it can't find an item in the container that matches the type. Why is this?
Jan 26, 2015 at 5:25 PM
Edited Jan 26, 2015 at 5:26 PM
Hi, I have been unsuccessful in reproducing this issue - are you able to provide some code to demonstrate?

This is what I have tried
[Fact]
public void NewJob_Always_CreatesInstance()
{
    var container = this.Register();
    var factory = new SimpleInjectorJobFactory(container);

    var result = factory.NewJob(typeof(Job1));

    Assert.IsType<Job1>(result);
}

public Container Register()
{
    var container = new Container();

    var jobTypes = from type in typeof(OptionExpiryJob).Assembly.GetExportedTypes()
                    where typeof(IJob).IsAssignableFrom(type)
                    where !type.IsAbstract && !type.IsGenericTypeDefinition
                    select type;

    container.RegisterAll<IJob>(jobTypes);

    return container;
}

public class SimpleInjectorJobFactory
{
    private readonly Container _container;

    public SimpleInjectorJobFactory(Container container)
    {
        _container = container;
    }

    public IJob NewJob(Type type)
    {
        return (IJob)_container.GetInstance(type);
    }
}
        
public class OptionExpiryJob { }

public interface IJob { }

public class Job1 : IJob { }

public class Job2 : IJob { }
Also, as an aside, why are you new ing up the JobDecorator and not registering it with the Container?
Jan 26, 2015 at 7:37 PM
Edited Jan 26, 2015 at 7:41 PM
> Simple Injector now says that it can't find an item in the container that matches the type. Why is this?

What kind of message do you get? Is the container throwing an exception? If so, please post the complete exception with stack trace here. If this is not an exception, what kind of message is this? Is this a diagnostic message that you get while using the diagnostic services?

Do note though that your initial registration with the call to RegisterAll never had any effect, since you were registering a collection of types, which is not the same as registering them seperately. Fortunately, registering them as a collection does mean that every type is verified by the container when calling Verify() and diagnosted when the diagnostic API is called.

But since your intention is to resolve those types using GetInstance, it is better to do the following:
var jobTypes = ...

jobTypes.ToList().ForEach(container.Register);
And if you use more decorators, you might want to register those decorators in the Simple Injector. This allows those decorators to be applied conditionally, and it allows the container to verify the decorators and their dependencies using the diagnostic services. To do that, you'll need a registration that is a bit different; it is described in this Stackoverflow answer (I just updated it).
Feb 1, 2015 at 11:40 AM
I didn't notice this before, but the initial question in this thread was actually triggered by a bug that was introduced in 2.6 and still exists in 2.7. The bug is described here and will be fixed in the next patch release.
Feb 1, 2015 at 4:43 PM
The just released v2.7.1 fixes the bug.