ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2019-07-02 20:52:14  阅读:275  来源: 互联网

标签:c dependency-injection idisposable autofac


我在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 

标签:c,dependency-injection,idisposable,autofac
来源: https://codeday.me/bug/20190702/1360066.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有