Если я создаю и удаляю свой контейнер несколько раз, то при каждом типе создания, который я заметил, из-за типизированной фабрики выделяется большой объем памяти (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
}
}