解析类型时LightInject IoC容器抛出计算器 [英] LightInject IoC container throws stackoverflow when resolving type

查看:405
本文介绍了解析类型时LightInject IoC容器抛出计算器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试走出LightInject IoC容器 http://www.lightinject.net/ 它抛出一个计算器例外解析类型ISomeService时:

When trying out the LightInject IoC container http://www.lightinject.net/ it throws a stackoverflow exception when resolving the type ISomeService:

所有类型登记在App_Start:

All types are registered in App_Start:

container.RegisterAssembly("MyApp*.dll");



,然后当我试图解决它的失败,并抛出一个计算器异常控制器:

And then when I try to resolve it in the controller it fails and throws a stackoverflow exception:

    public SomeController(ISomeService someService)
    {
         _someService = someService;
    }



它使用服务定位时,也有同样的错误
$ b

It also has the same error when using ServiceLocator:

ServiceLocator.Current.GetInstance<ISomeService>();



我已经通过追踪它,我可以看到它在LightInject的ServiceContainer类失败就在这里,但我不明白为什么失败呢。

I have traced it through and I can see that it is failing in the LightInject ServiceContainer class right here, but I don't see why it is failing yet.

public object GetInstance(Type serviceType)
{
    return GetDefaultDelegate(serviceType, true)(constants.Items);
}



调用GetDefaultDelegate后,执行路径结束回来的GetInstance再次引起无限环和一个堆栈溢出。

After calling GetDefaultDelegate, the execution path ends back in GetInstance again, causing an infinite loop and a stack overflow.

编辑2 - 进一步跟踪下来,它似乎被SomeService引起具有同时兼具构造和财产注入:

EDIT 2 - Have tracked this down further and it appears to be caused by SomeService having both constructor and property injection at the same time:

public class SomeService : ISomeService 
{
    public IAnotherService AnotherService { get; set; }
    public SomeService(IAnotherService anotherService)
    {
        AnotherService = anotherService;
    }
}

的依赖IAnotherService AnotherService正在通过构造注入财产,但没有打算用财产喷油器。

The dependency IAnotherService AnotherService is being injected via the constructor and the property, but there was no intention to use property injectors.

编辑3

有几层所有使用服务定位,所以我最初使用的NuGet添加李书福自己的项目应用,所以我有:

There are several layers in the app that all use ServiceLocator, so I initially added LI to its own project using NuGet, so I had:

MyApp.IoC.LightInject
MyApp.Repositories
MyApp.Services
MyApp.Web.UI

但它实际上不是必要将它添加到自己的项目,因为服务提供商定位器可以在UI层进行设置:

But it isn't actually necessary to add it to its own project because the service locator provider can be set in the UI layer:

var serviceLocator = new LightInjectServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => serviceLocator);



所以我刚才去掉多余的项目,并把包的NuGet到UI层代替。我还安装了LightInject.Annotation故意不叫container.EnableAnnotatedPropertyInjection()方法,以确保只有构造器注入被使用。它仍然抛出一个计算器

So I have just now removed the extra project and put the NuGet packages into the UI layer instead. I've also installed LightInject.Annotation and deliberately not called the container.EnableAnnotatedPropertyInjection() method, to ensure that only constructor injection is used. It is still throwing a stackoverflow.

要测试是否解决是工作,我只是在做这在我的HomeController.Index()方法:

To test if the resolving is working I am just doing this in my HomeController.Index() method:

public ActionResult Index()
{
    var a = ServiceLocator.Current.GetInstance<ISomeService>();
}



我加了一些控制台记录到ServiceController.GetInstance方法,使我可以看到什么方法调用的流程是,这是导致计算器。这是日志,结果是有点出乎意料。你可以看到,当它调用createDelegate方法()为ISomeService它最终想首先得到的HomeController的一个实例 - 这是为什么

I added some console logging to the ServiceController.GetInstance methods so that I could see what the flow of method calls was that was leading to the stackoverflow. This is the log, and the results are a bit unexpected. You can see that when it calls CreateDelegate() for ISomeService that it ends up trying to get an instance of HomeController first - why is that?

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

当我注释掉该服务的构造方法,解决工作和所有相关性物业注入解决。如果包括构造则抛出计算器例外。

When I comment out the service's constructor, the resolving works and all dependencies are resolved by property injection. If the constructor is included then it throws the stackoverflow exception.

和虽然解决只能通过属性时ISomeService的作品,我解决不了IAnotherService如果该服务包括ISomeService在其依赖。我希望上面的日志将阐明这个问题的一些情况。 LightInject的表现,到目前为止已经比团结显著好

And although the resolving ISomeService works when using properties only, I cannot resolve IAnotherService if that service includes ISomeService in its dependencies. I hope the log above will shed some light on the problem. The performance of LightInject so far has been significantly better than Unity

推荐答案

作为LightInject的作者,我会尽量回答尽我可以。

Being the author of LightInject I will try to answer the best I can.

首先,LightInject不应该抛出一个StackOverflowException,所以这是一些需要加以研究的基础上,你在这里描述的东西。

First of all, LightInject should never throw a StackOverflowException, so that is something that needs to be looked into based on what you describe here.

和我清醒地认识到物业注入是不是在这里你的意图,因为这将毫无意义的注射两次(构造函数和属性)的服务。

And I clearly understand that property injection was not your intention here as it would make little sense to inject the service twice (Constructor and Property).

有一些实际的事情,我们可以做,以避免依赖被注入的资产。

There are actually several things we can do to avoid the dependency to be injected into the property.


  1. 请在属性只读去掉公共setter方法。

  2. 注册通过使用文件提到的明确的服务注册什么样的服务。

  1. Make the property read-only by removing the public setter.
  2. Register the service by using what the documentation refers to as "explicit" service registration.

container.Register<ISomeService>(f => new SomeService(f.GetInstance<IAnotherService>())); 

这将导致公共属性被忽略,因为我们现在已经明确的有关如何解决依赖的SomeService类。

This will cause the public properties to be ignored because we have now been explicit about how to resolve the dependencies of the SomeService class.

请使用LightInject.Annotation的

Make use of LightInject.Annotation

这将确保只标有InjectAttribute属性将有它的依赖注入。在您的具体情况,这将意味着见好就收的财产是没有的属性。
。在组成根源,我们可以通过这种简单的配置启用此

This will make sure that only properties marked with the InjectAttribute will have its dependencies injected. In your specific case this would mean to just leave the property as is without the attribute. At the composition root, we can enable this by making this simple configuration.

container.EnableAnnotatedPropertyInjection(); 


我会如之前所说进一步调查成StackOverflowException,使这种情况适当调整。我首先想到的是,如果容器发现一种依赖,可享有注射既作为一个构造函数依赖和属性依赖抛出异常。

I will as said before investigate further into the StackOverflowException and make proper adjustments for this case. My first thought would be to throw an exception if the container finds a dependency that is eligible for injection both as a constructor dependency and a property dependency.

希望这有助于。

最好的问候

伯恩哈德·里希特

修改

虽然问题似乎解决了你的情况,我仍希望能够重现这一场考验。您得到一个异常的原因可能是不作为同时具有构造依赖性和相同类型的属性依赖的服务一样简单。

Although the problem seem to be solved for your case, I would still like to be able to reproduce this in a test. The reason that you get an exception is probably not as simple as the service having both a constructor dependency and a property dependency of the same type.

考虑这个服务

public class FooWithConstructorAndPropertyDependency : IFoo
{
    public FooWithConstructorAndPropertyDependency(IBar bar)
    {
        Bar = bar;
    }

    public IBar Bar { get; set; }
}



LightInject会很乐意注入的依赖。

LightInject will happily inject the dependency.

container.Register<IBar, Bar>();
container.Register<IFoo, FooWithConstructorAndPropertyDependency>();

container.GetInstance<IFoo>();



所以一定有别的东西,是造成异常。如果你能拿出重现异常,使这个可以处理最小的例子,我将不胜感激。我没有做什么失败了:)如果你选择做这方面的努力,您可以在这里发布或bernhard.richter@gmail.com寄给我进一步调查这是一个有点硬。

So there must be something else that is causing the exception. I would appreciate if you could come up with the smallest example that reproduces the exception so that this can be dealt with. It is a little hard for me do further investigations without something that fails:) If you choose to make this effort you can post it here or mail me at bernhard.richter@gmail.com.

这篇关于解析类型时LightInject IoC容器抛出计算器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆