0

I am fiddling with LightInject to try and set up a IoC solution containing a Domain proj, a Infrastructure proj, a MVC proj, and a DependencyResolution proj. Infrastructure, MVC, and DependencyResolution references Domain. MVC references DependencyResolution and DependencyResolution references LightInject.

The idea is that DependencyResolution registers all necessary dependencies at app startup. It has no knowledge of the controllers in the MVC proj at this time. Instead I set up a fallback routine to catch all unknown MVC Controller classes. In the fallback routine I then register the MVC Controller and return it. By doing this I expect this code to only be run one time, since it is only by the first hit the MVC Controller is not registered yet. But this is not the case. Instead I get a StackOverflowException because the fallback routine is hit every time the MVC Controller is asked for even though it was registered the first time.

So the question is why this happens? Is this expected behaviour and if so, why is that and how to get around it?

Edit: Here is the source code below.

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(DependencyResolution.App_Start.WebCommon), "Start")]
namespace DependencyResolution.App_Start
{
    static class WebCommon
    {
        private static readonly TempProject.LightInject.ServiceContainer _serviceContainer = new TempProject.LightInject.ServiceContainer();

        /// <summary>
        /// Starts the application
        /// </summary>
        public static void Start()
        {
            var container = _serviceContainer;
            RegisterServices(container);
            Domain.ServiceLocator.SetServiceLocator(() => new ServiceLocator(container));
        }

        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="container">The IoC container.</param>
        private static void RegisterServices(TempProject.LightInject.ServiceContainer container)
        {
            System.Func<TempProject.LightInject.ServiceRequest, object> fallback = request =>
                {
                    var serviceType = request.ServiceType;
                    container.Register(serviceType, serviceType);
                    return container.GetInstance(serviceType);
                };

            container.RegisterFallback((type, s) => type.Name.EndsWith("Controller"), request => fallback(request));
            var assembly = typeof(Domain.IServiceLocator).Assembly;
            container.RegisterAssembly(assembly);
        }
    }
}
SvanSr
  • 1
  • 2

1 Answers1

1

The RegisterFallback method expects a factory as the second parameter and does not seem to register the type in such a way that the container can resolve it.

Your factory needs to new up the instance and pass it back.

Func<ServiceRequest, object> fallback = request =>
{
    if (request.ServiceType == typeof(XYZController))
    {
        return new XYZController(container.GetInstance<IDependency>());
    }
    else
    {
        throw new InvalidOperationException(request.ServiceType.FullName);
    }
};

This might be an issue worth raising with the developers.


You could load the MVC assemblies using code something like this:

private IEnumerable<Assembly> LoadAssemblies(string folder)
{
    var dlls =
        from file in new DirectoryInfo(folder).GetFiles()
        where file.Extension == ".dll"
        select file.FullName;

    var assemblies = new List<Assembly>();

    foreach (string dll in dlls) {
        try {
            assemblies.Add(Assembly.LoadFile(dll));
        }
        catch { }
    }

    return assemblies;
}

And register all the controllers with the LightInject MVC Integration Package

qujck
  • 14,388
  • 4
  • 45
  • 74
  • Interesting. Why I want to register the unknown Controller in the fallback method is because I don't have any knowledge of the Controller types. The MVC assembly is not referenced and therefor I cannot new up the instance. – SvanSr Apr 30 '15 at 12:17
  • Maybe. I have to check that out. The thing is that I don't have a reference to the assembly and I can't do `container.RegisterControllers(typeof(MyMvcApplication).Assembly)` – SvanSr Apr 30 '15 at 12:35
  • If you [load](https://msdn.microsoft.com/en-us/library/system.reflection.assembly.load%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396) the assembly the `RegisterControllers` method should find and register all the controllers within it. – qujck Apr 30 '15 at 12:40