我在IDisposable对象和使用Autofac时发布了一般指南问题:Dependency Injection and IDisposable.不幸的是,我没有考虑我们项目中的一个特定场景,它实际上是一个独立的问题,所以会问它这里:
我有一个Repository对象来管理其中的会话对象的生命周期.因此,Repository对象是IDisposable并且销毁会话(Repository在构造时注入工厂委托,在第一次使用期间实例化会话,并且如果session不为null则在IDisposable中销毁会话).根据上面对*问题的引用,我理解注入了我的Repository对象的任何对象都不应该实现IDisposable,因为Autofac将处理我的存储库的处理,如果它正在注入它们.
每个提到的*线程,我已经开始清理我的对象的IDisposable用法,直到我偶然发现下面显示的NotificationPublisher类.有一些地方喜欢它注入类的IComponentContext实现作为工厂.解析在函数中手动执行,因为代码库不知道在运行时之前需要注入哪个处理程序.
public class NotificationPublisher : INotificationPublisher
{
private readonly IComponentContext _container;
private readonly INotificationManager _notificationManager;
public NotificationPublisher(IComponentContext container,
INotificationManager notificationManager)
{
_container = container;
_notificationManager = notificationManager;
}
public IEnumerable<IAlertSubscription> Publish(Account account,
INotificationInitiator owner, INotificationEntity entity,
Int32 severity, CheckCycleContext monitoringContext)
{
var alertSubscriptions =
_notificationManager.GetAlertSubscriptions(account, owner, severity);
foreach (var alertSubscription in alertSubscriptions)
{
var destination = alertSubscription.GetConsumer();
Type handlerType = typeof (INotificationHandler<,>)
.MakeGenericType(entity.GetType(), destination.GetType());
using (var handler =
(INotificationCustomHandler)_container.ResolveOptional(handlerType))
{
if (handler == null) continue;
try
{
Retry.Execute(() => (handler).Send(entity, destination), 3, 500);
monitoringContext.Record(CheckCycleContext.CycleSeverity.Information,
string.Format("NotificationPublisher.Publish:{0}/{1}",
entity.GetType().Name, destination.GetType().Name), "Success");
}
catch (Exception ex)
{
monitoringContext.Record(CheckCycleContext.CycleSeverity.Error,
string.Format("NotificationPublisher.Publish:{0}/{1}",
entity.GetType().Name, destination.GetType().Name), ex.Message, ex,
new {entity, destination});
}
}
}
return alertSubscriptions;
}
}
我假设由于INotificationCustomHandler是手动解析的,因此必须使用using语句手动处理,因为INotificationCustomHandler的实现注入了IManager的实现,这些实现注入了IRepository的实现.
因此,在这种情况下,我需要在我的代码库中传播IDisposable,这与我在之前的SO问题中所建议的相反.
如何在需要时通过工厂手动解析对象,然后让Autofac处理?
解决方法:
当Autofac解析实现IDisposable的组件时,此组件将与您在注册时配置的范围链接.当处理此范围时,所有链接的组件也将被处理.有关更多信息,请参见http://autofac.readthedocs.org/en/latest/lifetime/disposal.html.
在您的情况下,如果INotificationCustomHandler注册为InstancePerDependency(默认值)或InstancePerLifetimeScope,则由_container解析的INotificationCustomHandler将在_container也将被处理时处理.
如果这是你想要的,你不必调用.Dispose这些组件.
如果要手动控制对象的生命周期,可以创建自己的生命周期范围.
using(ILifetimeScope scope = this._container.BeginLifetimeScope())
{
var handler = (INotificationCustomHandler)scope.ResolveOptional(handlerType);
if(handler != null)
{
Retry.Execute(() => handler.Send(entity, destination));
}
} // handler will be disposed here if needed
你还应该看看owned instance,它就像一个迷你工厂.
if(!container.ComponentRegistry.IsRegistered(new TypedService(handlerType)))
{
continue;
}
Type handlerFactoryType = typeof(Func<>).MakeGenericType(
typeof(Owned<>).MakeGenericType(handlerType));
var handlerFactory = (Func<Owned<INotificationCustomHandler>>)container
.Resolve(handlerFactoryType);
using(Owned<INotificationCustomHandler> ownedHandler = handlerFactory())
{
INotificationCustomHandler handler = ownedHandler.Value;
Retry.Execute(() => handler.Send(entity, destination), 3, 500);
} // handler will be disposed here