在尝试 LightInject IoC 容器http://www.lightinject.net/时,它会在解析 ISomeService 类型时引发 stackoverflow 异常:
所有类型都在 App_Start 中注册:
container.RegisterAssembly("MyApp*.dll");
然后,当我尝试在控制器中解决它时,它会失败并引发 stackoverflow 异常:
public SomeController(ISomeService someService)
{
_someService = someService;
}
使用ServiceLocator时也出现同样的错误:
ServiceLocator.Current.GetInstance<ISomeService>();
我已经对其进行了跟踪,并且可以看到它在此处的 LightInject ServiceContainer 类中失败了,但我不明白它为什么会失败。
public object GetInstance(Type serviceType)
{
return GetDefaultDelegate(serviceType, true)(constants.Items);
}
调用 GetDefaultDelegate 后,执行路径又回到 GetInstance 结束,导致无限循环和堆栈溢出。
编辑 2 - 进一步追踪了这一点,它似乎是由 SomeService 同时具有构造函数和属性注入引起的:
public class SomeService : ISomeService
{
public IAnotherService AnotherService { get; set; }
public SomeService(IAnotherService anotherService)
{
AnotherService = anotherService;
}
}
依赖 IAnotherService AnotherService 正在通过构造函数和属性注入,但无意使用属性注入器。
编辑 3
应用程序中有几个层都使用 ServiceLocator,所以我最初使用 NuGet 将 LI 添加到它自己的项目中,所以我有:
MyApp.IoC.LightInject
MyApp.Repositories
MyApp.Services
MyApp.Web.UI
但实际上并不需要将其添加到自己的项目中,因为可以在 UI 层中设置服务定位器提供程序:
var serviceLocator = new LightInjectServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => serviceLocator);
所以我刚刚删除了额外的项目并将 NuGet 包放入 UI 层。我还安装了 LightInject.Annotation 并故意不调用 container.EnableAnnotatedPropertyInjection() 方法,以确保仅使用构造函数注入。它仍然抛出一个stackoverflow。
为了测试解析是否有效,我只是在我的 HomeController.Index() 方法中执行此操作:
public ActionResult Index()
{
var a = ServiceLocator.Current.GetInstance<ISomeService>();
}
我向 ServiceController.GetInstance 方法添加了一些控制台日志记录,以便我可以看到导致 stackoverflow 的方法调用流。这是日志,结果有点出乎意料。您可以看到,当它为 ISomeService 调用 CreateDelegate() 时,它最终会首先尝试获取 HomeController 的实例——这是为什么呢?
DoGetInstance: ISomeService. Key = ''
GetInstance: ISomeService
TryGetValue: ISomeService not found
TryAddValue: trying to add ISomeService now
CreateDynamicMethodDelegate: ISomeService
CreateDynamicMethodDelegate: calling CreateDelegate() for ISomeService
DoGetInstance: HomeController. Key = ''
GetInstance: HomeController
TryGetValue: HomeController not found
TryAddValue: trying to add HomeController now
CreateDynamicMethodDelegate: HomeController
CreateDynamicMethodDelegate: calling CreateDelegate() for HomeController
DoGetInstance: ISomeService. Key = ''
GetInstance: ISomeService
TryGetValue: ISomeService not found
TryAddValue: trying to add ISomeService now
CreateDynamicMethodDelegate: ISomeService
CreateDynamicMethodDelegate: calling CreateDelegate() for ISomeService
DoGetInstance: HomeController. Key = ''
GetInstance: HomeController
TryGetValue: HomeController not found
TryAddValue: trying to add HomeController now
CreateDynamicMethodDelegate: HomeController
CreateDynamicMethodDelegate: calling CreateDelegate() for HomeController
DoGetInstance: ISomeService. Key = ''
GetInstance: ISomeService
TryGetValue: ISomeService not found
TryAddValue: trying to add ISomeService now
CreateDynamicMethodDelegate: ISomeService
CreateDynamicMethodDelegate: calling CreateDelegate() for ISomeService
DoGetInstance: HomeController. Key = ''
GetInstance: HomeController
TryGetValue: HomeController not found
TryAddValue: trying to add HomeController now
CreateDynamicMethodDelegate: HomeController
CreateDynamicMethodDelegate: calling CreateDelegate() for HomeController
DoGetInstance: ISomeService. Key = ''
GetInstance: ISomeService
TryGetValue: ISomeService not found
TryAddValue: trying to add ISomeService now
CreateDynamicMethodDelegate: ISomeService
CreateDynamicMethodDelegate: calling CreateDelegate() for ISomeService
当我注释掉服务的构造函数时,解析工作和所有依赖项都通过属性注入解决。如果包含构造函数,则它会引发 stackoverflow 异常。
尽管解析 ISomeService 仅在使用属性时有效,但如果该服务在其依赖项中包含 ISomeService,我将无法解析 IAnotherService。我希望上面的日志能对这个问题有所了解。迄今为止,LightInject 的性能已经明显优于 Unity