【问题标题】:LightInject IoC container throws stackoverflow in fallback methodLightInject IoC容器在回退方法中抛出stackoverflow
【发布时间】:2015-04-29 13:11:05
【问题描述】:

我正在摆弄 LightInject 来尝试设置一个 IoC 解决方案,其中包含一个域项目、一个基础设施项目、一个 MVC 项目和一个 DependencyResolution 项目。 Infrastructure、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);
        }
    }
}

【问题讨论】:

  • 请显示后备例程

标签: ioc-container light-inject


【解决方案1】:

RegisterFallback 方法需要 factory 作为第二个参数,并且似乎没有以容器可以解析的方式注册类型。

您的工厂需要新建实例并将其传回。

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

这可能是一个值得向开发人员提出的issue。


您可以使用如下代码加载 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 Integration Package

【讨论】:

  • 有趣。为什么我要在回退方法中注册未知的Controller是因为我对Controller类型一无所知。未引用 MVC 程序集,因此我无法新建实例。
  • 也许吧。我必须检查一下。问题是我没有对程序集的引用,我不能这样做container.RegisterControllers(typeof(MyMvcApplication).Assembly)
  • 如果你 load 程序集 RegisterControllers 方法应该找到并注册其中的所有控制器。
猜你喜欢
  • 2013-09-26
  • 1970-01-01
  • 1970-01-01
  • 2017-06-27
  • 1970-01-01
  • 1970-01-01
  • 2014-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多