c# - 使用 CaSTLe Windsor 在开始新范围时我需要一个对象的新实例

标签 c# dependency-injection scope castle-windsor dispose

我正在尝试实现如下所示的对象构造,它在使用范围内创建一个新的 DbContext ,因此在离开使用范围时会被释放。因此,如下所示,我在两个单独的使用范围中创建了两个处理器对象。我想使用 CaSTLe Windsor 实现这一点。

        using (var context = new DbContext())
        {
            var processor = new Processor(context, new Parser(context, new Logger(context)), new Logger(context));
        }

        using (var context = new DbContext())
        {
            var processor = new Processor(context, new Parser(context, new Logger(context)), new Logger(context));
        }

我之前问过类似的问题Castle Windsor propogating inline dependencies这建议使用范围,但我无法让它按照我想要的方式工作。请参阅下面的完整程序。

using Castle.MicroKernel.Lifestyle;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using System;

namespace IOCTesting
{
    class Program
    {
        static void Main(string[] args)
        {
            var container = new WindsorContainer();

            container
                .Register(Component.For<IProcessor>()
                .ImplementedBy<Processor>());

            container
                .Register(Component.For<IParser>()
                .ImplementedBy<Parser>());

            container
                .Register(Component.For<ILogger>()
                .ImplementedBy<Logger>());

            container.Register(Component.For<DbContext>()
                .ImplementedBy<DbContext>()
                .LifeStyle
                .Scoped());

            using (container.BeginScope())
            {
                var processor = container.Resolve<IProcessor>();
            }

            using (container.BeginScope())
            {
                var processor = container.Resolve<IProcessor>();
            }
        }
    }

    public class DbContext : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("DbContext disposed.");
        }
    }

    public class Processor : IProcessor
    {
        private readonly DbContext _context;
        private readonly ILogger _logger;
        private readonly IParser _parser;

        public Processor(DbContext context, IParser parser, ILogger logger)
        {
            _context = context;
            _parser = parser;
            _logger = logger;
        }
    }

    public class Parser : IParser
    {
        private readonly DbContext _context;
        private readonly ILogger _logger;

        public Parser(DbContext context, ILogger logger)
        {
            _context = context;
            _logger = logger;
        }
    }

    public class Logger : ILogger
    {
        private readonly DbContext _context;

        public Logger(DbContext context)
        {
            _context = context;
        }
    }

    public interface IProcessor
    {
    }

    public interface IParser
    {
    }

    public interface ILogger
    {
    }
}

在退出第一个 container.BeginScope() 时调用 DbContext 上的 Dispose 方法,但在第二次调用容器时。 BeginScope() Dispose 方法在退出第二个作用域时不会被调用。

这意味着当第二个容器时,容器为我提供了相同的处置 DbContext 实例。 BeginScope() 被调用。本质上,我需要 DbContentcontainer.BeginScope() 中是 transient 的,并且容器在每个新实例上给我一个新的 DbContext 实例创建范围,以便在退出范围时始终将其释放。

希望这是有道理的。

最佳答案

IProcessorIParserILogger 也需要注册为Scoped

container.Register(Component.For<IProcessor>()
    .ImplementedBy<Processor>()
    .LifeStyle.Scoped());

对依赖于 DBContext 的所有组件执行此操作。

如果没有明确设置生活方式,则默认为单例。因此,当您第一次解析 IProcessor 时,单例被实例化,它的依赖项被解析,包括作用域 DBContext。在第一个作用域结束时,DBContext 被释放并释放,但是单例 IProcessor 仍然有一个对已释放的 DBContext 的引用。当您在第二个作用域中解析 IProcessor 时,将返回已实例化的单例,其中包含已处理的 DBContext

关于c# - 使用 CaSTLe Windsor 在开始新范围时我需要一个对象的新实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41255221/

相关文章:

c# - 当引发异常时返回堆栈跟踪时,C# 尾递归优化如何可能

c# - 我应该如何在事务中包装我的选择语句?

java - 如果没有 @Provides- 或 @Produces-annotated 方法,则无法提供 Dagger 2 Activity

r - 在函数内部使用 attributes()

Javascript 命名空间和私有(private)变量

c# - 在 C# 中使用 NumericComparer 代码,为什么我的 List.Sort() 会出现转换错误?

java - Guice 中延迟加载的提供者

dependency-injection - 运行注入(inject)代码的集成测试库的正确方法是什么?

c++ - 为什么派生类不能通过指向基类的指针访问其基类的 protected 成员?

c# - 试图找到文件中逻辑语句的数量