c# - 统一: Will get a StackOverflowException if I try to get a singleton that is registered in multiple mappings

标签 c# dependency-injection unity-container

给出以下两个接口(interface)和一个类:

interface IRepository<T> {}

interface IXRepository : IRepository<MyType> {}

class XRepository : IXRepository {}

我想要一个 XRepository 类型的单例可以通过 IRepository<MyType> 解决或 IXRepository .

我从以下代码开始:

public void Register<TFrom, TTo>(params Type[] typesToRegister) where TTo : TFrom
{
    parentContainer.RegisterType<TFrom, TTo>(new HierarchicalLifetimeManager());

    foreach (Type type in typesToRegister)
    {
        parentContainer.RegisterType(type, typeof(TTo), new HierarchicalLifetimeManager(), new InjectionFactory(c => c.Resolve<TFrom>()));
    }
}

这是客户端方法调用:

service.Register<IRepository<MyType>, XRepository>(typeof(IXRepository));

执行此语句后的 childContainer 的注册(标题:RegisteredType、MappedToType、Name 和 LifetimeManagerType):

  • typeof(IRepository<MyType>) , typeof(XRepository>) , null , typeof(HierarchicalLifetimeManager)
  • typeof(IXRepository) , typeof(XRepository) , null , typeof(HierarchicalLifetimeManager)

但是如果我尝试通过 IRepository<MyType> 来解决(或 IXRepository ),将抛出 StackOverflowException。这是因为 new InjectionFactory(c => c.Resolve<TFrom>()) 中的 lambda 表达式被一次又一次地执行。 有谁知道引擎盖下发生了什么?请求 IRepository<MyType> 时执行 lambda 表达式的原因是什么? ?

我发现如果你在注册时提供了一个名字(在这个例子中是“gaga”),不会抛出 StackOverflowException:

  • typeof(IRepository<MyType>) , typeof(XRepository>) , <强> "gaga" , typeof(HierarchicalLifetimeManager)
  • typeof(IXRepository) , typeof(XRepository) , null , typeof(HierarchicalLifetimeManager)

谢谢, 罗杰

最佳答案

您可以将具体类型 XRepository 注册为单例,然后注册要使用该类型解析的两个接口(interface):

container.RegisterType<XRepository>(new HierarchicalLifetimeManager());
container.RegisterType<IRepository<String>, XRepository>();
container.RegisterType(typeof(IXRepository), typeof(XRepository));

如果运行以下代码,您将看到应用了单例行为并考虑了子容器:

var isSingleton = container.Resolve<IRepository<String>>() == container.Resolve<IXRepository>();

var outerInstance = container.Resolve<IXRepository>();
using(var childContainer = container.CreateChildContainer())
{
    isSingleton = childContainer.Resolve<IRepository<String>>() == childContainer.Resolve<IXRepository>();
    var isHierarchichalSingleton = outerInstance  != childContainer.Resolve<IXRepository>();
}

附带说明一下,您的问题可以通过更简单的方式重现。 这可能是 Unity 中的一个错误 这是根据 Unity 的设计(检查@Lukazoid 评论和回答),例如:

interface IFoo { }
interface IBar { }
class Foo : IFoo, IBar  { }

container.RegisterType<IFoo, Foo>();
container.RegisterType<IBar, Foo>(new InjectionFactory(c => c.Resolve<IFoo>()));
var foo = container.Resolve<IFoo>();

关于c# - 统一: Will get a StackOverflowException if I try to get a singleton that is registered in multiple mappings,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30502431/

相关文章:

java - 在 JSF 2.0 中注入(inject) Bean

java - 创建两个相同的 bean 依赖不同

c# - 使用 Unity 的 Web Api 核心项目

configuration - Unity 应该在代码还是配置文件中配置?

c# - IUnityContainer.Resolve<T> 抛出错误,声称它不能与类型参数一起使用

c# - VS 2008上的ServiceStack.redis配置

c# - 如何在 C# 中异步读取结束进程输出?

c# - 可以使子类仅通过静态属性实例化

c# - 在 C# 中阻止函数调用

objective-c - 在 View Controller 之间传递应用程序上下文