Autofac,IDisposable接口和手动调用.Resolve在某些情况下 [英] Autofac, IDisposable and manually calling .Resolve in certain circumstances

查看:929
本文介绍了Autofac,IDisposable接口和手动调用.Resolve在某些情况下的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在IDisposable对象和使用Autofac时发布了一般性指南问题: Autofac和IDisposable 。不幸的是,我没有在我们的项目中考虑一个特定的情况,它是一个独立的问题,它是独立的,因此会在这里问:

I've posted a general guideline question when it comes to IDisposable objects and using Autofac here: Autofac and IDisposable. Unfortunately, I did not account for one particular scenario in our project and it's really a separate question that stands on its own, so will ask it here:

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

I have a Repository object that manages the life of a session object inside it. Thus, Repository object is IDisposable and destroys session (Repository is injected with a factory delegate at construction, instantiates session during first usage, and destroys session in IDisposable if session is not null). Per reference to StackOverflow question above, I understand that any object that is injected with my Repository object should not be implementing IDisposable since Autofac will handle disposing of my repositories, if it is injecting them.

根据提到的StackOverflow线程,我已经开始清理IDisposable使用从我的对象,直到我偶然发现如下所示的NotificationPublisher类。有几个地方喜欢它的类注入与实现的IComponentContext作为一个工厂。解析在一个函数中手动执行,因为代码库不知道在运行时之前需要注入什么处理程序。

Per mentioned StackOverflow thread, I've started cleaning up IDisposable usage from my objects until I stumbled upon NotificationPublisher class shown below. There are a few places like it where classes are injected with implementation of IComponentContext that acts as a factory. Resolution happens manually in a function, because the codebase does not know what handler needs to be injected until the 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;
    }
}



我假设自从INotificationCustomHandler被手动解决,它必须使用 语句手动处理,因为INotificationCustomHandler的实现注入了使用IRepository的实现注入的IManager的实现。

I'm assuming that since INotificationCustomHandler is manually resolved, it must be manually disposed with the using statement, becuase implementations of INotificationCustomHandler are injected with implementations of IManager that is injected with implementations of IRepository.

因此,在这种情况下,我需要传播IDisposable在我的代码库,这违反了我在前面的问题中的建议。

Thus, in this situation I need to propagate IDisposable throughout my codebase which goes against what I was suggested in the prior SO question.

如何在需要时通过工厂手动解析对象,但让Autofac处理?

推荐答案

Autofac 解析实现 IDisposable 的组件时,在您注册时已配置。当这个范围将被处置时,所有链接的组件也将被处理。请参见 http://autofac.readthedocs.org/en/latest/lifetime/dispose。 html 了解更多信息。

When Autofac resolve a component that implements IDisposable this one will be linked with scope that has been configured when you registered it. When this scope will be disposed, all linked components will be disposed too. See http://autofac.readthedocs.org/en/latest/lifetime/disposal.html for more information.

在您的情况下,如果 INotificationCustomHandler 注册为 InstancePerDependency _container 解析的 ,如果 _container 也会被处置。

In your case, if INotificationCustomHandler is registered as InstancePerDependency (default) or InstancePerLifetimeScope, INotificationCustomHandler resolved by _container, will be disposed when _container will be disposed too.

如果这是你想要的,你不必在这些组件上调用 .Dispose

If this is what you want, you don't have to call .Dispose on these components.

如果要手动控制对象的生命周期,可以创建自己的生命周期范围。

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

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 have a look to 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 

这篇关于Autofac,IDisposable接口和手动调用.Resolve在某些情况下的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆