LightInject IoC контейнер хвърля stackoverflow в резервен метод

Занимавам се с LightInject, за да опитам да настроя IoC решение, съдържащо Domain proj, Infrastructure proj, MVC proj и DependencyResolution proj. Инфраструктура, MVC и DependencyResolution препратки към домейн. MVC препраща към DependencyResolution и DependencyResolution препраща към LightInject.

Идеята е, че DependencyResolution регистрира всички необходими зависимости при стартиране на приложението. Понастоящем няма познания за контролерите в MVC proj. Вместо това създадох резервна рутина за улавяне на всички неизвестни класове на MVC контролер. След това в резервната рутина регистрирам MVC контролера и го връщам. Като правя това, очаквам този код да се изпълнява само веднъж, тъй като само при първото попадение MVC контролерът все още не е регистриран. Но това не е така. Вместо това получавам StackOverflowException, защото резервната рутина е ударена всеки път, когато се поиска MVC контролерът, въпреки че е регистриран за първи път.

Така че въпросът е защо това се случва? Това очаквано поведение ли е и ако е така, защо е така и как да го заобиколите?

Редактиране: Ето изходния код по-долу.

[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);
        }
    }
}

person SvanSr    schedule 29.04.2015    source източник
comment
Моля, покажете резервната рутина   -  person qujck    schedule 29.04.2015


Отговори (1)


Методът RegisterFallback очаква фабрика като втори параметър и изглежда не регистрира типа по такъв начин, че контейнерът да може да го разреши.

Вашата фабрика трябва да обнови екземпляра и да го върне обратно.

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

Това може да е проблем, който си струва да повдигнете пред разработчиците.


Можете да заредите MVC модулите, като използвате нещо подобно на код:

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;
}

И регистрирайте всички контролери с LightInject пакета за интегриране на MVC

person qujck    schedule 30.04.2015
comment
интересно Защо искам да регистрирам неизвестния контролер в резервния метод е, защото нямам никакви познания за типовете контролери. Сглобяването на MVC не е споменато и поради това не мога да актуализирам екземпляра. - person SvanSr; 30.04.2015
comment
Може би. Трябва да проверя това. Работата е там, че нямам препратка към сборката и не мога да направя container.RegisterControllers(typeof(MyMvcApplication).Assembly) - person SvanSr; 30.04.2015
comment
Ако зареди сборката, която методът RegisterControllers трябва да намери и регистрира всички контролери в нея. - person qujck; 30.04.2015