Autofac, IDisposable and manual call. Recover under certain circumstances

I posted a general reference question when it comes to IDisposable objects and using Autofac here: Injection Dependency and IDisposable . Unfortunately, I did not take into account one specific scenario in our project, and this is really a separate issue, which stands on its own, so ask it here:

I have a repository object that governs the life of the session object inside it. Thus, the repository object is IDisposable and destroys the session (the repository is introduced by the factory delegate when building, starts the session during first use, and destroys the session in IDisposable if the session is not null). Regarding the StackOverflow question link above, I understand that any object that is entered with my repository object should not implement IDisposable, since Autofac will handle deleting my repositories if it inserts them.

In the mentioned StackOverflow thread, I started clearing the use of IDisposable from my objects until I came across the NotificationPublisher class shown below. There are several places where classes are introduced with an implementation of IComponentContext, which acts like a factory. Permission is done manually in the function, because the code base does not know which handler must be entered before runtime.

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; } } 

I assume that since INotificationCustomHandler is manually enabled, it must be manually deleted using the using statement, because the INotificationCustomHandler implementations are introduced with the IManager implementations that introduce the IRepository implementations.

Thus, in this situation, I need to distribute IDisposable in my code base, which contradicts what I suggested in the previous SO question.

How to manually resolve objects through factories when necessary, and let Autofac process the utility?

+4
c # dependency-injection idisposable autofac
source share
1 answer

When Autofac permits a component that implements IDisposable , it will be associated with the scope that was configured when it was registered. When this area is deleted, all related components will also be deleted. See http://autofac.readthedocs.org/en/latest/lifetime/disposal.html for more details.

In your case, if INotificationCustomHandler registered as InstancePerDependency (by default) or InstancePerLifetimeScope , the INotificationCustomHandler allowed by _container will be deleted when _container is _container .

If this is what you want, you do not need to call .Dispose for these components.

If you want to manually control the lifetime of your objects, you can create your own life span.

 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 

You should also take a look at the owned instance , which acts like a mini factory.

 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 
+2
source share

All Articles