c# – Autofac,IDisposable和手动呼叫.在某些情况下解决

我在IDisposable对象和使用Autofac时发布了一般指南问题:
Dependency Injection and 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<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 
点赞