Это аналогично тому, как указано в другом месте и подробно в этом блоге . У меня это работает с использованием Windsor 2.5.4 в значительной степени, как указано в блоге, но решил перейти на использование Windsor 3. Когда я это сделал, я заметил, что использование памяти приложением со временем возрастает - я догадался, что это будет компоненты не выпускались.
В посте блога было несколько модификаций кода, которые, возможно, вызвали изменение поведения.
Вот мой перехватчик AutoRelease (прямо из поста в блоге, здесь для удобства и ленивый;))
[Transient]
public class AutoReleaseHandlerInterceptor : IInterceptor
{
private static readonly MethodInfo Execute = typeof(IDocumentHandler).GetMethod("Process");
private readonly IKernel _kernel;
public AutoReleaseHandlerInterceptor(IKernel kernel)
{
_kernel = kernel;
}
public void Intercept(IInvocation invocation)
{
if (invocation.Method != Execute)
{
invocation.Proceed();
return;
}
try
{
invocation.Proceed();
}
finally
{
_kernel.ReleaseComponent(invocation.Proxy);
}
}
}
Одним из моих отклонений от поста в блоге является селектор, который использует типизированная фабрика: -
public class ProcessorSelector : DefaultTypedFactoryComponentSelector
{
protected override Func<IKernelInternal, IReleasePolicy, object> BuildFactoryComponent(MethodInfo method,
string componentName,
Type componentType,
IDictionary additionalArguments)
{
return new MyDocumentHandlerResolver(componentName,
componentType,
additionalArguments,
FallbackToResolveByTypeIfNameNotFound,
GetType()).Resolve;
}
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
return null;
}
protected override Type GetComponentType(MethodInfo method, object[] arguments)
{
var message = arguments[0];
var handlerType = typeof(IDocumentHandler<>).MakeGenericType(message.GetType());
return handlerType;
}
}
Что может быть заметно, так это то, что я не использую распознаватель по умолчанию. (Возможно, в этом проблема ...).
public class MyDocumentHandlerResolver : TypedFactoryComponentResolver
{
public override object Resolve(IKernelInternal kernel, IReleasePolicy scope)
{
return kernel.Resolve(componentType, additionalArguments, scope);
}
}
(для краткости я опустил ctor - там ничего особенного не происходит, он просто вызывает базовый ctor).
Причина, по которой я это сделал, заключалась в том, что распознаватель по умолчанию будет пытаться разрешить по имени, а не по типу и сбою. В этом случае я знаю, что мне нужно разрешать только по типу, поэтому я просто переопределил метод Resolve.
Последним элементом головоломки станет установщик.
container.AddFacility<TypedFactoryFacility>()
.Register(
Component.For<AutoReleaseHandlerInterceptor>(),
Component.For<ProcessorSelector>().ImplementedBy<ProcessorSelector>(),
Classes.FromAssemblyContaining<MessageHandler>()
.BasedOn(typeof(IDocumentHandler<>))
.WithService.Base()
.Configure(c => c.LifeStyle.Is(LifestyleType.Transient)),
Component.For<IDocumentHandlerFactory>()
.AsFactory(c => c.SelectedWith<ProcessorSelector>()));
Пошагово через код, вызывается перехватчик , и выполняется предложение finally (например, я не правильно понял имя метода). Однако компонент, кажется, не освобожден (использование счетчика производительности показывает это. Каждый вызов фабричного метода create увеличивает счетчик на единицу).
До сих пор мой обходной путь состоял в том, чтобы добавить метод void Release (обработчик IDocumentHandler) к моему фабричному интерфейсу, а затем после того, как он выполняет метод handler.Process (), он явно освобождает экземпляр обработчика, и это, кажется, делает задание - счетчик производительности увеличивается, а по завершении обработки - вниз).
Вот фабрика:
public interface IDocumentHandlerFactory
{
IDocumentHandler GetHandlerForDocument(IDocument document);
void Release(IDocumentHandler handler);
}
А вот как я это использую:
IDocumentHandlerFactory handler = _documentHandlerFactory.GetHandlerForDocument(document);
handler.Process();
_documentHandlerFactory.Release(handler);
Делая Release явно, отрицаешь необходимость перехватчика, но мой реальный вопрос - почему это поведение отличается между выпусками?