【问题标题】:How can I properly set up a cache on a typedfactory using the decorator pattern (Castle Windsor)?如何使用装饰器模式(Castle Windsor)在 typedfactory 上正确设置缓存?
【发布时间】:2013-06-08 19:47:19
【问题描述】:

我正在使用 Castle Windsor,并且正在尝试使用装饰器模式在 TypedFactory 上设置缓存。在我尝试处理 Windsor 容器(关闭应用程序时)之前,它工作正常。基本上,我的问题是,当我试图处置 CachedFactory 时,TypedFactory 已经被处置了。

这是我的问题的简化示例:

using System;
using System.Collections.Generic;
using System.Threading;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.Windsor;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            // Setting up the container
            var container = new WindsorContainer();
            container.AddFacility<TypedFactoryFacility>();
            container.Register(
                Component.For<IItemFactory>().ImplementedBy<CachedItemFactory>(), //decorator pattern
                Component.For<IItemFactory>().AsFactory(),
                Component.For<IItem>().ImplementedBy<Item>().LifestyleTransient()
                );

            // Resolving
            var itemFactory = container.Resolve<IItemFactory>();

            // Desired behavior. Works as expected.
            IItem item1 = itemFactory.Create("Item1");
            IItem item2 = itemFactory.Create("Item2");
            IItem anotherItem1 = itemFactory.Create("Item1");
            Console.WriteLine("Item1 == Item2: {0}", item1 == item2); //false
            Console.WriteLine("Item1 == anotherItem1: {0}", item1 == anotherItem1); //true

            // Here is my problem. It throws ObjectDisposedException from _itemFactory in the Dispose function of CachedItemFactory
            container.Dispose();

            Console.WriteLine("End of program");
            Console.ReadKey();
        }
    }

    public interface IItem
    {
        string Name { get; }
    }

    public class Item : IItem
    {
        public Item(string name)
        {
            Name = name;
            Thread.Sleep(1000); //It takes time to create this object
        }

        public string Name { get; private set; }
    }

    public interface IItemFactory
    {
        IItem Create(string name);
        void Release(IItem item);
    }

    public class CachedItemFactory : IItemFactory, IDisposable
    {
        private readonly Dictionary<string, IItem> _cache = new Dictionary<string, IItem>();
        private readonly IItemFactory _itemFactory;

        public CachedItemFactory(IItemFactory itemFactory)
        {
            _itemFactory = itemFactory;
        }

        public IItem Create(string name)
        {
            if (!_cache.ContainsKey(name))
                _cache.Add(name, _itemFactory.Create(name));
            return _cache[name];
        }

        public void Release(IItem item)
        {
        }

        public void Dispose()
        {
            foreach (var item in _cache)
            {
                _itemFactory.Release(item.Value);
            }
            _cache.Clear();
        }
    }
}

对我做错了什么有任何想法吗?任何概念(架构)错误?

我尝试了以下但没有成功:

  1. 在 CachedItemFactory 之前注册 TypedFactory(并将 CachedItemFactory 标记为 IsDefault):不起作用,同样的错误
  2. 手动实现基本工厂而不是使用 TypedFactory:同样的问题

这行得通:

  1. 手动实现一个基本工厂,在CachedItemFactory之前注册,并将CachedItemFactory标记为IsDefault...但是感觉不对(脆弱)...

有没有cmets?

非常感谢!

【问题讨论】:

标签: caching castle-windsor decorator typed-factory-facility


【解决方案1】:

您将缓存和类型化工厂都注册为单例(隐式)。 如果您将 TypeFactory 注册为 Transient,它可能会(不完全确定)在缓存工厂之后立即处理。

但是,由于您只尝试清理工厂的已解析组件,因此您也可以简单地省略 Dispose 中的代码,因为类型化工厂将在释放时释放它的所有组件。

【讨论】:

    猜你喜欢
    • 2013-08-26
    • 2012-09-20
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 2012-04-26
    • 2013-01-29
    • 1970-01-01
    • 2010-10-07
    相关资源
    最近更新 更多