Autofac,IDisposable和手动呼叫。在某些情况下解决

我在IDisposable对象和使用Autofac时发布了一般指南问题: dependency injection和IDisposable 。 不幸的是,我没有考虑到我们项目中的一个特定场景,它实际上是一个独立的问题,所以会在这里问:

我有一个Repository对象来管理其中的会话对象的生命周期。 因此,Repository对象是IDisposable并且销毁会话(Repository在构造时注入工厂委托,在第一次使用期间实例化会话,并且如果session不为null则在IDisposable中销毁会话)。 根据上面对StackOverflow问题的引用,我理解注入了我的Repository对象的任何对象都不应该实现IDisposable,因为Autofac会处理我的存储库,如果它正在注入它们。

每个提到的StackOverflow线程,我已经开始清理我的对象中的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 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解析的_container将在_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 

你还应该看看拥有像迷你工厂一样的实例 。

 if(!container.ComponentRegistry.IsRegistered(new TypedService(handlerType))) { continue; } Type handlerFactoryType = typeof(Func<>).MakeGenericType( typeof(Owned<>).MakeGenericType(handlerType)); var handlerFactory = (Func>)container .Resolve(handlerFactoryType); using(Owned ownedHandler = handlerFactory()) { INotificationCustomHandler handler = ownedHandler.Value; Retry.Execute(() => handler.Send(entity, destination), 3, 500); } // handler will be disposed here