我有一个完整的(和破碎的)C#应用程序下面,生成堆栈溢出异常。如果您查看源代码,您将看到为什么会有堆栈溢出异常,所以我没有真正考虑诊断为什么会发生这种情况,我想知道处理它的最佳方式是什么。什么是在Unity容器上调用dispose的最佳方式?
1)所有对unity的引用都封装在一个名为Registry的类中,所以我可以毫无困难地进行升级。我不希望unitycontainer在可能的情况下丢弃其他类。从理论上讲,如果出现这种情况,我应该可以升级到5,或者如果我的性格发生了剧烈的变化,甚至可以将它与ninject或其他DI框架互换。
2)我想注册表由统一容器控制,以便它可以在容器控制类的构造函数中使用。 (例如FirstSingleInstance)
3)IRegistry和Registry从IDisposable继承,因为我认为这是处理统一容器的好习惯。
4)注册表在它自己的构造函数中构造了Unity容器,所以我假设我应该在调用registry.dispose时处理统一容器。 5)所有其他由Registry控制的类都应该是单实例类,所以我使用ContainerControlledLifetimeManager注册它们。我预计这些实例将在集装箱处置时处置。
处理这种情况的最佳做法是什么?
a)不要在注册表中调用dispose - 让它为进程线程的生命而生存?
b)不要试图让统一容器控制注册表(以及扩展名,UnityContainer)。这种在Registry上调用dispose的方式不会导致stackoverflow异常。然后,我会如何构建FirstSingleInstance类,这是我必须审查的。
d)其他?
下面是我写的应用程序,拥有所有相关部件
using System;
using Microsoft.Practices.Unity;
namespace DIProblem.Console
{
class Program
{
static void Main(string[] args)
{
IRegistry registry = CreateRegistry();
IFirstSingleInstance theInstance = registry.Resolve<IFirstSingleInstance>();
theInstance.DoThis();
registry.Dispose(); // stack overflow here because of infinite dispose loop
}
static IRegistry CreateRegistry() => new Registry();
}
public class FirstSingleInstance : IFirstSingleInstance
{
private IRegistry _registry;
public FirstSingleInstance(IRegistry reg)
{
_registry = reg;
}
public void DoThis()
{
System.Console.WriteLine("This Was Done.");
_registry.Resolve<ISecondSingleInstance>().DoThisToo();
}
}
public class SecondSingleInstance : ISecondSingleInstance
{
private IRegistry _registry;
public SecondSingleInstance(IRegistry reg)
{
_registry = reg;
}
public void DoThisToo()
{
System.Console.WriteLine("This Was Done too.");
}
}
public interface ISecondSingleInstance
{
void DoThisToo();
}
public interface IFirstSingleInstance
{
void DoThis();
}
public class Registry : IRegistry, IDisposable
{
public Registry()
{
_container = new UnityContainer();
RegisterInstance<IFirstSingleInstance, FirstSingleInstance>();
RegisterInstance<ISecondSingleInstance, SecondSingleInstance>();
_container.RegisterInstance<IRegistry>(this);
}
private UnityContainer _container;
public void RegisterInstance<T1, T2>() where T2 : class, T1 => _container.RegisterType<T1, T2>(new ContainerControlledLifetimeManager());
public T Resolve<T>() => _container.Resolve<T>();
public void Dispose()
{
Dispose(true);
System.GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
_container?.Dispose();
_container = null;
}
}
public interface IRegistry : IDisposable
{
T Resolve<T>();
void RegisterInstance<T1, T2>() where T2 : class, T1;
}
}
感谢您的任何帮助出路似乎是合理的。
那么为什么你在容器中注册'IRegistry'? – Steven
因为FirstSingleInstance类将其作为公共构造函数中的参数接受。 – Jason
为什么它需要它作为依赖项?我可以想象它需要容器,但不是注册表,它基本上是你的组合根。 – Steven