Контейнер IoC LightInject вызывает переполнение стека в резервном методе

Я возился с LightInject, чтобы попытаться настроить решение IoC, содержащее проект домена, проект инфраструктуры, проект MVC и проект DependencyResolution. Инфраструктура, MVC и DependencyResolution ссылаются на домен. MVC ссылается на DependencyResolution, а DependencyResolution ссылается на LightInject.

Идея заключается в том, что DependencyResolution регистрирует все необходимые зависимости при запуске приложения. В настоящее время он ничего не знает о контроллерах в проекте MVC. Вместо этого я настроил резервную процедуру, чтобы перехватывать все неизвестные классы контроллера 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;
}

И зарегистрируйте все контроллеры с помощью пакета интеграции MVC LightInject.

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