Типизированная проблема с заводской памятью - PullRequest
0 голосов
/ 04 апреля 2011

Если я создаю и удаляю свой контейнер несколько раз, то при каждом типе создания, который я заметил, из-за типизированной фабрики выделяется большой объем памяти (200 КБ для этого образца, но в реальном приложении ~ 2 МБ), что приводит к исключению OutOfMemory

Без заводской памяти автогенерации растет намного медленнее.

// используя автоматически созданную фабрику -> память растет намного больше ... (см. Task mngr)

Component.For (). AsFactory (c => c.SelectedWith ())

// использование моей фабрики без памяти -> память растет намного меньше

// Component.For (). ImplementedBy ()

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;
using System.Reflection;
using Castle.Facilities.FactorySupport;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Handlers;
using Castle.Core;
using Castle.MicroKernel;
using Castle.MicroKernel.Context;

namespace CastlePlayground1.AppConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                for (int i = 0; i < 10; i++)
                {

                    IWindsorContainer container = buildContainer();

                    string converterName = "Converter1";
                    object obj2convert = 1;
                    object objResult;

                    var cmp = container.Resolve<ConverterHelper1>();

                    objResult = cmp.Convert(converterName, obj2convert);

                    Console.WriteLine("{0} has been converted to {1} by {2}", obj2convert, objResult, converterName);

                    container.Release(cmp);


                    converterName = "Converter2";
                    cmp = container.Resolve<ConverterHelper1>();

                    objResult = cmp.Convert(converterName, obj2convert);

                    Console.WriteLine("{0} has been converted to {1} by {2}", obj2convert, objResult, converterName);

                    container.Release(cmp);


                    container.Dispose();

                    Console.WriteLine("{0} ended", i);
                    System.Threading.Thread.Sleep(2 * 1000);
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.Message);
            }

            Console.ReadLine();
        }

        private static IWindsorContainer buildContainer()//string configPath
        {
            IWindsorContainer container = null;

            try
            {
                container = new WindsorContainer();
                container.Kernel.Resolver.AddSubResolver(new ArrayResolver(container.Kernel));
                container.AddFacility<TypedFactoryFacility>();
                container.Register
                (
                    Component.For<CustomTypedFactoryComponentSelector, ITypedFactoryComponentSelector>(),
                    AllTypes.FromThisAssembly()
                        .BasedOn<Contracts.IConverter>().WithService.Base()
                        .Configure(c => c.Named(c.Implementation.Name))
                        .Configure(c => c.LifeStyle.Singleton),
                    Component.For<Contracts.IConverterFactory>().AsFactory(c => c.SelectedWith<CustomTypedFactoryComponentSelector>()),
                    //Component.For<Contracts.IConverterFactory>().ImplementedBy<Contracts.ConverterFactory>(),


                    Component.For<ConverterHelper1>().LifeStyle.Transient
                );
            }
            catch (Exception exc)
            {
                throw;
            }

            return container;
        }
    }

    /// <summary>
    /// ArrayResolver from:
    /// http://hammett.castleproject.org/?p=257
    /// </summary>
    public class ArrayResolver : ISubDependencyResolver
    {
        private readonly IKernel kernel;

        public ArrayResolver(IKernel kernel)
        {
            this.kernel = kernel;
        }

        public object Resolve(CreationContext context, ISubDependencyResolver parentResolver,
                              ComponentModel model,
                              DependencyModel dependency)
        {
            return kernel.ResolveAll(dependency.TargetType.GetElementType(), null);
        }

        public bool CanResolve(CreationContext context, ISubDependencyResolver parentResolver,
                               ComponentModel model,
                               DependencyModel dependency)
        {
            return dependency.TargetType != null &&
                   dependency.TargetType.IsArray &&
                   dependency.TargetType.GetElementType().IsInterface;
        }
    }

}
namespace CastlePlayground1.AppConsole
{

    public class CustomTypedFactoryComponentSelector : DefaultTypedFactoryComponentSelector
    {

        protected override string GetComponentName(MethodInfo method, object[] arguments)
        {
            if (method.Name == "GetById" && arguments.Length == 1 && arguments[0] is string)
            {
                return (string)arguments[0];
            }

            return base.GetComponentName(method, arguments);

        }
    }

    public class ConverterHelper1
    {
        Contracts.IConverterFactory _converterFactory;
        public ConverterHelper1(Contracts.IConverterFactory converterFactory)
        {
            _converterFactory = converterFactory;
        }

        public object Convert(string converterName, object obj2convert)
        {
            object obj = null;

            var cmp = _converterFactory.GetById(converterName);
            obj = cmp.Convert(obj2convert);
            return obj;
        }
    }


    public class Converter1 : Contracts.IConverter
    {
        #region IConverter Members

        public object Convert(object input)
        {
            return 1;
        }

        #endregion
    }

    public class Converter2 : Contracts.IConverter
    {
        #region IConverter Members

        public object Convert(object input)
        {
            return 2;
        }

        #endregion
    }
}



namespace CastlePlayground1.AppConsole.Contracts
{
    public interface IConverter
    {
        object Convert(object input);
    }

    public interface IConverterFactory : IDisposable
    {
        IConverter GetById(string converterName);
    }

    public class ConverterFactory : IConverterFactory
    {
        IConverter[] _converters;
        public ConverterFactory(IConverter[] converters)
        {
            _converters = converters;
        }

        #region IConverterFactory Members

        public IConverter GetById(string converterName)
        {
            return _converters.Where(c=>c.GetType().Name==converterName).FirstOrDefault();
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            //throw new NotImplementedException();
        }

        #endregion
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...