首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在联合容器上调用dispose的最佳方式是什么?

在联合容器上调用dispose的最佳方式是什么?
EN

Stack Overflow用户
提问于 2017-09-23 03:37:26
回答 1查看 3.9K关注 0票数 0

我有一个完整的(和坏的) C#应用程序,在下面生成堆栈溢出异常。如果您查看源代码,您将看到为什么会出现堆栈溢出异常,所以我并不是真的在诊断为什么会发生这种情况,我想知道处理它的最佳方法是什么。

1)所有对统一的引用都封装在一个名为Registry的类中,这样我就可以毫不费力地升级。我不想在可能的情况下把其他的班级扔在一起。理论上,如果/当它出现时,我应该能够升级到5,或者如果我的处理方式发生了很大的变化,我甚至可以用ninject或其他DI框架来交换它。

2)我希望注册表由统一容器控制,以便它可以在容器控制类的构造函数中使用。(如FirstSingleInstance)

3) IRegistry和Registry两者都继承了IDisposable,因为我认为处理统一容器是很好的做法。

4)注册表在它自己的构造函数中构造了统一容器,所以我假设在调用registry.dispose时我也应该处理统一容器。

5)注册表控制的所有其他类都是单实例类,因此我将它们注册到ContainerControlledLifetimeManager中。我预计当容器被释放时,这些实例将被释放。

处理这种情况的最佳做法是什么?

( a)不要在注册表上调用dispose --让它在进程线程的生命周期中存活?

( b)不要尝试由统一容器控制注册表(扩展为UnityContainer)。这样,在注册表上调用dispose不会导致堆栈溢出异常。然后,我将如何让统一构造FirstSingleInstance类,这是我必须回顾的事情。

( d)其他?

这是我写的应用程序,里面有所有相关的部分

代码语言:javascript
运行
复制
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;
    }
}

谢谢你以任何看似合理的方式提供帮助。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-23 12:19:56

下面的代码避免使用服务定位器反模式,而是完全依赖于构造器注入作为应用控制反转的模式。结果是一个更简单、更易于维护和更可测试的应用程序,它不会导致任何堆栈溢出异常。

代码语言:javascript
运行
复制
class Program
{
    static void Main(string[] args)
    {
        using (var container = Registry.BuildContainer())
        {
            var theInstance = registry.Resolve<IFirstSingleInstance>();
            theInstance.DoThis();
        }
    }
}

public static class Registry
{
    public static UnityContainer BuildContainer()
    {
        var container = new UnityContainer();

        container.RegisterType<IFirstSingleInstance, FirstSingleInstance>(Singleton);
        container.RegisterType<ISecondSingleInstance, SecondSingleInstance>(Singleton);

        return container;
    }

    private static ContainerControlledLifetimeManager Singleton => 
        new ContainerControlledLifetimeManager();
}

public interface ISecondSingleInstance
{
    void DoThisToo();
}

public interface IFirstSingleInstance
{
    void DoThis();
}

public class FirstSingleInstance : IFirstSingleInstance
{
    private ISecondSingleInstance _second;

    public FirstSingleInstance(ISecondSingleInstance second)
    {
        _second = second;
    }

    public void DoThis()
    {
        System.Console.WriteLine("This Was Done.");
        _second.DoThisToo();
    }
}

public class SecondSingleInstance : ISecondSingleInstance
{
    public SecondSingleInstance(/* other dependencies here */)
    {
    }

    public void DoThisToo()
    {
        System.Console.WriteLine("This Was Done too.");
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46375781

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档